metaeducation / rebol-issues

6 stars 1 forks source link

'self is being bound by For, Repeat, Foreach, Map-each and Remove-each #1529

Closed rebolbot closed 8 years ago

rebolbot commented 14 years ago

Submitted by: Ladislav

This makes it problematic to use the above control functions inside an object spec block, or inside a module spec block, or script (where 'self would otherwise refer to the user context). Basically it would cause a problem for all code that refers to 'self, no matter where it is defined.

This is similar to bug #447 (closures used to do the same thing and now don't).

>> same? 'self for i 1 1 1 ['self]
== false  ; should be true

CC - Data [ Version: alpha 97 Type: Bug Platform: All Category: Native Reproduce: Always Fixed-in:alpha 98 ]

rebolbot commented 14 years ago

Submitted by: BrianH

From Steeve in AltME and the blog:

Perhaps the usefulness of having self in FOR loops has been underestimated. See that counter-example. - How to construct a block of objects from serialized values, in a nutshell.

>> map-each [a b][1 2 3 4 5 6][copy self]
== [make object! [
        a: 1
        b: 2
    ] make object! [
        a: 3
        b: 4
    ] make object! [
        a: 5
        b: 6
    ]]
rebolbot commented 14 years ago

Submitted by: BrianH

From Andreas in AltME (abolka here):

Steeve, while this may be considered a nice trick, I don't think it's worth keeping the nasty self around.

map-each [a b] [1 2 3 4 5 6] [copy bind? 'a] does the same and is more explicit about what you want.
rebolbot commented 14 years ago

Submitted by: BrianH

Steeve that is a nice trick. That could come in handy for converting from records that are stored in fixed-length format in a block to save space, to object format for passing along to generalized functions that accept objects.

However, Andreas is right: You don't need the 'self trick to do that, you can always use BIND?, especially since all loop contexts have at least one field other than the hidden 'self. And as cool as that trick is, it is unlikely to be as common as using 'self to refer to the outer object, module or script context.

rebolbot commented 14 years ago

Submitted by: Ladislav

one more example in hope, that it will be understandable enough. First, the description in words: we define a function obtaining a block of code, which uses e.g. a Repeat loop. During the loop, the Block argument shall be executed too, but bound to the loop context, to be able to use the loop variable (s). The code looks as follows:
a-function: func [block [block!]] [
    repeat i 1 [do-in-context block 'i]
]
do-in-context: func [block [block!] context [word! object!]] [do bind block context]

I hope, that everyone understands, that this may well be a part of a real-world application, but my example is minimized to contain only the constructs that illustrate the problem. Now, in R2 the block will be executed "in the right context", being able to use the cycle variable 'i. In R3, the block is executed "in the wrong context", since the 'self variable will be bound, which was unsolicited.

Generally, I consider 'self binding as unsolicited for purposes like: loop constructs, functions, closures, use, etc. For a similar opinion, see also #447

rebolbot commented 14 years ago

Submitted by: BrianH

Ladislav, R2's BIND also binds the hidden 'self field in code blocks (less hidden in R2 than R3, but still). Loop functions are a separate issue.

rebolbot commented 14 years ago

Submitted by: Ladislav

in the core-tests suite