Project

General

Profile

Actions

Feature #18815

open

instance_{eval,exec} vs Proc#>>

Added by zverok (Victor Shepelev) 2 months ago. Updated 2 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:108757]

Description

measure = proc { p "self=#{self}"; size }
multiply = proc { '*' * _1 }

'test'.instance_eval(&measure)
# "self=test"
#  => 4

'test'.instance_eval(&measure >> multiply)
# "self=main"
# NameError (undefined local variable or method `size' for main:Object)

So, Proc#>> produces a proc which is not suitable for instance_eval/instance_exec. The same as the "naive" implementation:

# Naive sequence
sequence = proc { measure.call.then(&multiply) }

...but is it possible to make the combination to behave like the first proc is not wrapped into an additional layer of indirection?.. Intuitively, it shouldn't be completely impossible.

# What I meant actually:
intended = proc { size.then(&multilpy) }
"test".instance_eval(&intended)
# => "****"

The example is invented, the question is "whether this should work", not "how to solve this task with another approach".


Related issues 1 (0 open1 closed)

Is duplicate of Ruby master - Bug #18067: Composite procs with `instance_exec` aren't executed within the context of the receiverRejectedActions
Actions #1

Updated by jeremyevans0 (Jeremy Evans) 2 months ago

  • Is duplicate of Bug #18067: Composite procs with `instance_exec` aren't executed within the context of the receiver added

Updated by jeremyevans0 (Jeremy Evans) 2 months ago

This is basically the same as #18067. I don't think it's a bug, because you get the exact same behavior with manual composition (see example in #18067). However, I welcome feedback from other committers.

Updated by zverok (Victor Shepelev) 2 months ago

@jeremyevans0 (Jeremy Evans) I don't think it is a "bug", but maybe a nice feature to have (composite procs being a bit smarter than just a really thin syntax sugar over what you could've done manually). The realistic case I have is a constant with definitions of how to handle some huge list of parameters, it might look like that:

FLATTEN = -> { [*_1] }
IDENTITY = -> { _1 }
DATE = -> { Date.parse(_1) }

TRANSFORMATIONS = {
  param1: FLATTEN,
  param2: FLATTEN,
  param3: IDENTITY,
  # ....
}

...and then, some processing is more complicated and depends on current class' context:

param4: -> { allowed?(:something) ? _1 : DEFAULT }

...now, if param4 should also be flattened before handling, I was happy I can write

param4: FLATTEN >> -> { allowed?(:something) ? _1 : DEFAULT }

...until I understood it wouldn't work :)

Obviously, I can (and did)

param4: -> { allowed?(:something) ? FLATTEN.(_1) : DEFAULT }

...but the >> version looked much more clear, especially in big params list, so you can clearly read: this is flattened, this is flattened and then also post-processed.

Updated by jeremyevans0 (Jeremy Evans) 2 months ago

  • Backport deleted (2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN)
  • Tracker changed from Bug to Feature

zverok (Victor Shepelev) wrote in #note-3:

@jeremyevans0 (Jeremy Evans) I don't think it is a "bug", but maybe a nice feature to have

That makes sense. Switching to feature request.

Actions

Also available in: Atom PDF