Bug! in assignment to date! values with stacked set-path values
[1/25] from: al::bri::xtra::co::nz at: 12-Nov-2002 20:04
Here's an example:
>> x: now/date
== 12-Nov-2002
>> x/day: 1 ; Try individually; OK!
== 1
>> x
== 1-Nov-2002
>> x/month: 1 ; Try individually; OK!
== 1
>> x
== 1-Jan-2002 ; And the expected value is shown.
>> x: now/date ; Get fresh value.
== 12-Nov-2002
>> x/month: x/day: 1 ; Now stack up the assignments.
== 1 ; correct value is returned, but...
>> x
== 12-Jan-2002 ; Note that only the MONTH is altered...
>> x: now/date ; Get fresh value.
== 12-Nov-2002
>> x/day: x/month: 1 ; Reverse the order....
== 1
>> x ; Note that only the DAY is altered...
== 1-Nov-2002
It's buggy on Rebol/Core, Rebol/View, Rebol/Base and all the beta versions.
The work around for now is to separate the assignments, as shown in the
first few steps.
I've just sent this in to feedback.
Andrew Martin
ICQ: 26227169 http://valley.150m.com/
[2/25] from: lmecir:mbox:vol:cz at: 12-Nov-2002 9:46
Hi Andrew,
----- Original Message -----
From: "Andrew Martin"
Subject: [REBOL] Bug! in assignment to date! values with stacked set-path
values
> >> x: now/date ; Get fresh value.
> == 12-Nov-2002
> >> x/month: x/day: 1 ; Now stack up the assignments.
> == 1 ; correct value is returned, but...
> >> x
> == 12-Jan-2002 ; Note that only the MONTH is altered...
This is an artifact that is caused by immutability of dates. (you may
remember the discussion on the subject) The
x/month: 1
expression is only a hack, no real mutation occurs. Exactly the same hack
can be written to modify the bits of integer numbers as I have shown.
Regards
-L
[3/25] from: carl:cybercraft at: 12-Nov-2002 23:31
It's not just dates Andrew...
>> a: 1.2.3
== 1.2.3
>> a/1: a/2: 4
== 4
>> a
== 4.2.3
Carl.
On 12-Nov-02, Andrew Martin wrote:
> Here's an example:
>>> x: now/date
<<quoted lines omitted: 27>>
> ICQ: 26227169 http://valley.150m.com/
> -><-
--
Carl Read
[4/25] from: rotenca:telvia:it at: 12-Nov-2002 14:45
Hi Ladislav, Andrew, Carl
> This is an artifact that is caused by immutability of dates. (you may
> remember the discussion on the subject) The
>
> x/month: 1
>
> expression is only a hack, no real mutation occurs. Exactly the same hack
> can be written to modify the bits of integer numbers as I have shown.
It seems to me that the mutation hack is not enough to explain this. The
problem is that all the value are pre-fetched before the first assign start,
else with or without mutation the result should be right. Instead, the
pre-fetch works only with mutable values. The bug is prefetch the value of
set-path.
Neither parens can correct the problem.
Look at this:
>> a: "aaa" probe a/2: (a: "bbb" #"c") a
aca
== "bbb"
As you can see the a/2 continue to refer to the old string "aaa" also when the
parens block has changed the 'a value with "bbb". I can be wrong but i do not
see any mutation hack here.
---
Ciao
Romano
[5/25] from: joel::neely::fedex::com at: 12-Nov-2002 8:09
Re: Bug! in assignment to date! values with stacked set-pathvalues
Hi, Ladislav,
Let's not start *that* again!!! ;-)
In addition, I don't think that dates are the issue here.
Ladislav Mecir wrote:
> Hi Andrew,
> ----- Original Message -----
<<quoted lines omitted: 8>>
> > == 12-Jan-2002 ; Note that only the MONTH is altered...
> This is an artifact that is caused by immutability of dates...
Instead of pointing the WayBack machine to "Mutability", let's set
it to "Referential Transparency" instead. The principle of RT is
that expressions which yield equivalent results should be freely
interchangeable without altering the net value. Since
1 + 1
and
2
are equivalent expressions, we'd expect the larger expressions
pick "abcde" 1 + 1
and
pick "abcde" 2
to yield equivalent values. A notation/implementation in which
thing1: someval
yields a resulting value equivalent to
someval
and yet
thing2: thing1: someval
behaves differently from
thing1: someval
thing2: someval
defies both the principle of RT and (for those who claim that
REBOL is for non-programmers) what I believe most "normal humans"
would expect from such a rewriting, as REBOL normally allows one
to "chain" setting expressions freely (as long as the result of
each setting expression is equivalent to the set value):
>> x/2: a: foo/month: b: 1
== [0 1 0]
>> x
== [0 1 0]
>> a
== 1
>> foo
== 12-Jan-2002
>> b
== 1
The disclaimer, of course, is due to the fact that setting X/2
yields a value that is *not* equivalent to 1, but in the case of
FOO/MONTH the value yielded *is* equivalent to 1!
As with the concurrent discussion of REVERSE (but even more so in
this case), it's distressing to have specific instances of *very*
non-intuitive behavior marring an otherwise nice notation, when
the user has access to no documentation explaining such cases!
As a demonstration of my "even more so" position, consider the
following ...
>> foo: now/date
== 12-Nov-2002
>> blk: [foo/month: 1]
== [foo/month: 1]
>> do blk
== 1
>> foo
== 12-Jan-2002
>> foo: now/date
== 12-Nov-2002
>> foo/day: do blk
== 1
>> foo
== 1-Nov-2002
>> foo: now/date
== 12-Nov-2002
>> x: do blk foo/day: x
== 1
>> foo
== 1-Jan-2002
>> foo: now/date
== 12-Nov-2002
>> foo/day: do blk
== 1
>> foo
== 1-Nov-2002
... which shows the presence of hidden state that can cause
the effect we're discussing to be buried arbitrarily deeply!
I really have to regard this as a serious flaw of documentation
(at least!), and respectfully repeat my passionate request for
the kind of official, authoritative documentation that would
allow users to understand what is happening and why!
(I have my own opinions, but they're not authoritative!)
-jn-
--
; Joel Neely joeldotneelyatfedexdotcom
REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip
do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] {
| e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]
[6/25] from: lmecir:mbox:vol:cz at: 12-Nov-2002 17:22
Hi Joel,
> I really have to regard this as a serious flaw of documentation
> (at least!), and respectfully repeat my passionate request for
> the kind of official, authoritative documentation that would
> allow users to understand what is happening and why!
My POV differs from yours in two points:
a) I think, that the situation is a result of a "hack solution". The
strange
behaviour looks like being unexpected not just by users, but by
implementors too (IMO). This can (at least for me) explain, why it isn't
documented.
b) The behaviour looks like not being designed with these effects in mind
and it needs a second thought. That is why I am not asking for a
documentation change/addendum.
Best regards
-L
[7/25] from: joel:neely:fedex at: 12-Nov-2002 11:16
Re: Bug! in assignment to date! values with stackedset-pathvalues
Hi, Ladislav,
Pardon my disagreeing, but I think we're really agreeing! ;-)
(I think perhaps I used too much shorthand, and I'm too pessimistic!)
Ladislav Mecir wrote:
> Hi Joel,
> > I really have to regard this as a serious flaw of documentation
<<quoted lines omitted: 5>>
> The "strange" behaviour looks like being unexpected not just by
> users, but by implementors too (IMO)...
...
> b) The behaviour looks like not being designed with these effects
> in mind and it needs a second thought...
>
I included the "(at least!)" to hint that I suspect this was the
result of some ad hoc implementation choice(s), rather than a
consequence of strategic design. I had originally worded my views
a bit more strongly, but toned them down before hitting "Send" to
avoid leaving the impression that I was REBOL-bashing. Sorry if
I was too elliptic!
> This can (at least for me) explain, why it isn't documented.
>
But there are lots of things that aren't documented! The lack of
authoritative specification for what the built-in features of the
language are *supposed* to do is IMHO a significant impediment to
its adoption in the larget world of professional programming.
When faced with the question of "What does this do?":
- Computing Scientists say, "Let's derive it from basic principles!"
- Software Engineers say, "Let's look it up in the specification!"
- Hackers say, "Let's try it and see what happens!"
> That is why I am not asking for a documentation change/addendum.
>
I think it would be easier to get a description of what REBOL
currently does (and *then* discuss possible changes) than to begin
with a request for changes in the absence of any clear statement of
intent. Past discussions about cases where REBOLS behavior has
surprised its users (even the most supportive ones) have drawn a
response of, "Let REBOL be REBOL!" Hence my position of, "OK! Then
first tell me clearly what REBOL is!"
However, I'm sure we agree in the hope that documenting REBOL's
current behavior wouldn't be the end of the conversation!!!
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
[8/25] from: lmecir::mbox::vol::cz at: 13-Nov-2002 13:58
Hi,
> When faced with the question of "What does this do?":
>
> - Computing Scientists say, "Let's derive it from basic principles!"
Yes, I like this one and a lot of list members at least tried to pretend,
that this was the case.
> - Software Engineers say, "Let's look it up in the specification!"
This is more desirable, than the last one, but...
> - Hackers say, "Let's try it and see what happens!"
This is what happened, (at least in this case).
> I think it would be easier to get a description of what REBOL
> currently does (and *then* discuss possible changes) than to begin
> with a request for changes in the absence of any clear statement of
> intent.
Well, the question is, if we *can* get that. If this was an unknown
feature
(for implementors), they couldn't have documented it. I think,
that the only complete behaviour documentation is the interpreter. (or the
source code of it, which we aren't supposed to get, are we?)
Every software project can contain some bugs. What you are asking for is
some form of specification, which was used to build the interpreter. I don't
know, whether this is/isn't considered a trade secret? Moreover, there is
still a possibility, that such a thing isn't complete.
> Past discussions about cases where REBOLS behavior has
> surprised its users (even the most supportive ones) have drawn a
> response of, "Let REBOL be REBOL!" Hence my position of, "OK! Then
> first tell me clearly what REBOL is!"
I think, that instead of letting REBOL be whatever, it is more useful to
propose an improvement/ask for a feature that we think is missing. (like a
referential transparency etc.) The only trouble is, that every user has
his/her own list of preferences and they may be incompatible.
But, let me play a devill's advocate: "REBOL is a moving target.":-)
> However, I'm sure we agree in the hope that documenting REBOL's
> current behavior wouldn't be the end of the conversation!!!
I think, that it neither would be the start nor the end of the conversation,
because even now we may say, that some features are documented, but the
documentation isn't in agreement with the real state of affairs! Curiously,
some things are better than the documentation is suggesting.
[9/25] from: lmecir:mbox:vol:cz at: 13-Nov-2002 18:16
Re: Bug! in assignment to date! values with stacked set-path values
Hi Romano,
I tried to tell, that the behaviour was caused by the fact, that the whole
thing was only a hack.
The hack was most probably not well thought out and the same hack could have
been made for integers and has been made for issues.
> It seems to me that the mutation hack is not enough to explain this. The
> problem is that all the value are pre-fetched before the first assign
start,
> else with or without mutation the result should be right. Instead, the
> pre-fetch works only with mutable values. The bug is prefetch the value of
> set-path.
You are right. The behaviour can be corrected, although that might influence
the speed of the interpreter...
> Neither parens can correct the problem.
> Look at this:
>
> >> a: "aaa" probe a/2: (a: "bbb" #"c") a
> "aca"
> == "bbb"
>
> As you can see the a/2 continue to refer to the old string "aaa" also when
the
> parens block has changed the 'a value with "bbb". I can be wrong but i do
not
> see any mutation hack here.
>
> ---
> Ciao
> Romano
Ah, I didn't read your whole post, sorry. This is interesting and it is a
proof of the fact, that the whole path business is a hack in Rebol (no
surprise).
When we are at it, we shall ask RT to change the path business more
thoroughly to introduce referential transparency. I am afraid, that this
change will affect the way Rebol parser (make block! / load) works, because
I would suggest to not treat #"(" and #")" as ordinary delimiters. Instead
Rebol should treat them as "forbidden" characters, which aren't allowed to
occur in words. Nevertheless,
a/(1 + 2)
should differ from
a / (1 + 2)
, where the former can be treated as a path, while the latter as an
expression, which divides A by 3.
What do you think about the fact, that the difference is small, which may
lead to confusions?
-L
[10/25] from: rotenca:telvia:it at: 14-Nov-2002 12:22
Hi Ladislav,
> You are right. The behaviour can be corrected, although that might influence
> the speed of the interpreter...
Yes, but func are already fetched twice, why not path?
> When we are at it, we shall ask RT to change the path business more
> thoroughly to introduce referential transparency. I am afraid, that this
> change will affect the way Rebol parser (make block! / load) works, because
> I would suggest to not treat #"(" and #")" as ordinary delimiters. Instead
> Rebol should treat them as "forbidden" characters, which aren't allowed to
> occur in words.
I don't undertand well why. Can you make an example?
> Nevertheless,
> a/(1 + 2)
<<quoted lines omitted: 4>>
> What do you think about the fact, that the difference is small, which may
> lead to confusions?
the problem is general. Many cases in Rebol are of this nature:
2/ 1
2 / 1
2 /1
---
Ciao
Romano
[11/25] from: lmecir:mbox:vol:cz at: 14-Nov-2002 14:02
Hi Romano,
> > When we are at it, we shall ask RT to change the path business more
> > thoroughly to introduce referential transparency. I am afraid, that this
> > change will affect the way Rebol parser (make block! / load) works,
because
> > I would suggest to not treat #"(" and #")" as ordinary delimiters.
Instead
> > Rebol should treat them as "forbidden" characters, which aren't allowed
to
> > occur in words.
>
> I don't undertand well why. Can you make an example?
the example is below:
> > a/(1 + 2)
> >
<<quoted lines omitted: 4>>
> > , where the former can be treated as a path, while the latter as an
> > expression, which divides A by 3.
The reason is this:
a/(1 + 1): 5
should be treated as
a/2: 5
IMO
[12/25] from: rotenca:telvia:it at: 14-Nov-2002 15:41
Hi Ladislav,
> The reason is this:
>
> a/(1 + 1): 5
>
> should be treated as
>
> a/2: 5
Yes, i undertand this. What i do not understand is what you means with "make
#"(" a forbidden char in words".
Are you asking something as:
to-word "(" ;== error!
And if this is the case, why?
I'm also asking myself if this notation:
a/(1 + 1) ;== a/2
is compatible with the less agressive evaluation of new betas. What do you
think?
---
Ciao
Romano
[13/25] from: lmecir:mbox:vol:cz at: 14-Nov-2002 16:31
Hi Romano,
> What i do not understand is what you means with "make
> #"(" a forbidden char in words".
It means, that [(a)] should contain a paren! containing a word as it did,
but (a)/(b) shall differ from (a) / (b), i.e. parens shall be treated
specifically - neither as possible word characters, nor as ordinary
delimiters.
Currently we have:
length? [(a)/(b)] ; == 3
, while I am proposing, that we should get:
length? [(a)/(b)] ; == 1
and
type? first [(a)/(b)] ; == path!
OTOH, it is OK to obtain:
length? [(a) / (b)] ; == 3
What do you think?
One may try to check an analogical situation: [a]/[b] versus [a] / [b]. What
would be the best solution in that case?
> Are you asking something as:
>
> to-word "(" ;== error!
>
> And if this is the case, why?
This case doesn't matter, any solution is acceptable to me.
> I'm also asking myself if this notation:
>
> a/(1 + 1) ;== a/2
>
> is compatible with the less agressive evaluation of new betas. What do you
> think?
I would suggest even less aggressive evaluation: if a word is evaluated,
like e.g.
a
, the result should be the same as the result of
:a
with *exactly* one exception: if A is a function, then the function should
be evaluated in the former case.
I am sure, that this kind of word evaluation isn't incompatible with the
suggested path evaluation change.
Ciao
-L
[14/25] from: rotenca:telvia:it at: 14-Nov-2002 18:12
Hi Ladislav
> It means, that [(a)] should contain a paren! containing a word as it did,
> but (a)/(b) shall differ from (a) / (b), i.e. parens shall be treated
> specifically - neither as possible word characters, nor as ordinary
> delimiters.
...
> This case doesn't matter, any solution is acceptable to me.
Only this? Well: everything was clear from the beginning. :-)
> OTOH, it is OK to obtain:
>
> length? [(a) / (b)] ; == 3
>
> What do you think?
I agree. I should like at least to use compose on path:
b: 1
compose a/(b) ;== a/1
and get-word in this case:
>> x: func [/a][a]
>> b: 'a;== a
>> x/:b ;==true
Now the latter print none as it would called without any refinement and this
seems to me a bug.
> One may try to check an analogical situation: [a]/[b] versus [a] / [b]. What
> would be the best solution in that case?
Is a too radical proposal the following?
[[a] 2]/[a] ; ==2
[a 2 b 3]/b ; ==3
a: [[a] 1 [b] 2]
a/[b];==2
a/([b]) ;==2
Going in this direction we'll can embed a whole Rebol program in a path!
instead of a block! :-)
---
Ciao
Romano
[15/25] from: lmecir:mbox:vol:cz at: 15-Nov-2002 8:07
Hi Romano,
> Yes, but func are already fetched twice, why not path?
(-: It looks to me, that we always want the opposite of the actual
implementation! :-)
I think (Praetera censeo), that functions should be fetched just once and
that
a: func [x] [type? :x 1]
b: func [x] [type? :x 2]
a a: :b
Should yield 1 (Carthaginem esse delendam).
Joel can call my request "the principle of the least surprise", but there is
another reason to change the current behaviour: we can avoid some nasty
errors/interpreter crashes/bugs this way.
OTOH, set-paths are different animals.
a: "1"
a/1: (a: "3" #"2")
a
Here everybody is surprised, that the last operation, which is the path-set
somewhat magically "occurs" (at least partially) before the paren!
evaluation, which, again, seems to violate "the principle of the least
surprise".
Nevertheless, paths can be evaluated like above and it makes perfect sense
to me:
a: make object! [f: does [a: make object! [f: does [2]] 1]]
a/f ; == 1
This makes perfect sense to me, although:
probe a
make object! [
f: func [][2]
]
Another thing I want to mention is, that while
a: "12"
a/1: #"3" ; == "32"
the same operation used for dates yields:
a: now
a/day: 1 ; == 1
, which doesn't look unified.
-L
[16/25] from: rotenca:telvia:it at: 18-Nov-2002 12:19
Hi Ladislav
> I think (Praetera censeo), that functions should be fetched just once and
> that
>
> a: func [x] [type? :x 1]
> b: func [x] [type? :x 2]
> a a: :b
>
> Should yield 1 (Carthaginem esse delendam).
I agree.
> Nevertheless, paths can be evaluated like above and it makes perfect sense
> to me:
Do you means that set-path should be fetched only one time?
I think that the problem with path could arise from the fact that set-path
does not exists as true datatype!, it is only the last item in the path that
make rebol thinks it is a set-path. To truely understand the path, it should
evaluate the path itself to find its real meaning.
The result is a strange behaviour: a set-path which works like a path
x: func [/b][3]
type? first [x/b:];== set-path!
x/b: ;==3
in the last istruction no set action has been done, the last set-path has been
used like a normal path.
This happens, i think, because type? looks only at the form of path and it see
a set-word, while evaluation sees a function call and a refinement!.
Another strange thing:
:x ;== function?
:x/b ;== 3
> the same operation used for dates yields:
>
> a: now
> a/day: 1 ; == 1
>
> , which doesn't look unified.
this is for me the mutation hack at work.
---
Ciao
Romano
[17/25] from: lmecir:mbox:vol:cz at: 18-Nov-2002 13:09
Hi Romano,
> > Nevertheless, paths can be evaluated like above and it makes perfect
sense
> > to me:
>
> Do you means that set-path should be fetched only one time?
I mean, that paths should be evaluated differently, than set-paths (the
order of evaluation should be different for these two datatypes).
> I think that the problem with path could arise from the fact that set-path
> does not exists as true datatype!, it is only the last item in the path
that
> make rebol thinks it is a set-path.
I don't agree with that, every Rebol datatype has got a type attribute
attached to it, IMO.
> The result is a strange behaviour: a set-path which works like a path
>
> x: func [/b][3]
> type? first [x/b:];== set-path!
> x/b: ;==3
This is unexpected, but it may be justified as an attempt to "do something
meaningful" instead of firing an error.
> Another strange thing:
> :x ;== function?
> :x/b ;== 3
This is consistent with something like a/:i, when the interpreter considers
such a thing to be a path:
type? first [:x/b] ; == path!
Ciao
-L
[18/25] from: rotenca:telvia:it at: 18-Nov-2002 14:42
Hi Ladislav
> > Do you means that set-path should be fetched only one time?
>
> I mean, that paths should be evaluated differently, than set-paths (the
> order of evaluation should be different for these two datatypes).
OK!
> > I think that the problem with path could arise from the fact that set-path
> > does not exists as true datatype!, it is only the last item in the path
> that
> > make rebol thinks it is a set-path.
>
> I don't agree with that, every Rebol datatype has got a type attribute
> attached to it, IMO.
Yes: load set it, but it can only set it with a rule: it ends with #":".
The evaluation then can demonstrate another thing: that it was not a set-path
but a function call with refinement.
> > The result is a strange behaviour: a set-path which works like a path
> >
<<quoted lines omitted: 3>>
> This is unexpected, but it may be justified as an attempt to "do something
> meaningful" instead of firing an error.
I do not think the same. Here the attempt is not set something, but only to
evaluate the path. If a set-path is by default "set the value referenced by
the path" this construct should trigger an error or a crash. Obviously this
can be corrected adding an error! ad hoc, but ist shows for me the interpreter
behaviour.
> > Another strange thing:
> > :x ;== function?
> > :x/b ;== 3
>
> This is consistent with something like a/:i, when the interpreter considers
> such a thing to be a path:
>
> type? first [:x/b] ; == path!
Yes, get-path does not exist. The problem for me is that using a function with
a refinement and using a function without any refinement are two different
things at all, if one use a get-word.
Often I'm asking myself: what are advantages of refinements in functions?
Often i see only the bad side.
---
Ciao
Romano
[19/25] from: lmecir:mbox:vol:cz at: 18-Nov-2002 16:37
Hi Romano,
> > > The result is a strange behaviour: a set-path which works like a path
> > >
<<quoted lines omitted: 3>>
> >
> > This is unexpected, but it may be justified as an attempt to "do
something
> > meaningful" instead of firing an error.
>
> I do not think the same. Here the attempt is not set something, but only
to
> evaluate the path. If a set-path is by default "set the value referenced
by
> the path" this construct should trigger an error or a crash. Obviously
this
> can be corrected adding an error! ad hoc, but ist shows for me the
interpreter
> behaviour.
Yes, you are right. This shows the way how the interpreter is built.
Nevertheless, there are at least two cases, when I would consider it a bug.
The first one is the subject of this thread and the second one is the case
of two-times-fetched functions.
> Often I'm asking myself: what are advantages of refinements in functions?
> Often i see only the bad side.
The refinements have big disadvantages, as I see it.
Some disadvantages:
1) the function must test, how it has been called, although that information
has already been processed to get the arguments
2) the refinement system works well only if any refinement combination is
legal
, otherwise the function must check the combination on its own
The trouble is, that the refinements have advantages too.
The main advantage is a lower pollution of the system dictionary.
[20/25] from: g:santilli:tiscalinet:it at: 18-Nov-2002 15:28
Hi Romano,
On Monday, November 18, 2002, 2:42:45 PM, you wrote:
>> I don't agree with that, every Rebol datatype has got a type attribute
>> attached to it, IMO.
RPT> Yes: load set it, but it can only set it with a rule: it ends with #":".
RPT> The evaluation then can demonstrate another thing: that it was not a set-path
RPT> but a function call with refinement.
I agree with Ladislav.
>> obj: context [a: 1 b: 2]
>> p: to path! [obj a]
== obj/a
>> do reduce [p]
== 1
>> p: to path! [obj a:]
== obj/a:
>> do reduce [p 2]
** Script Error: Invalid path value: a
** Near: obj/a: 2
>> p: to set-path! [obj a]
== obj/a:
>> do reduce [p 2]
== 2
>> p: to set-path! [obj a:]
== obj/a::
>> do reduce [p 2]
** Script Error: Invalid path value: a
** Near: obj/a:: 2
In particular:
>> f: func [/ref] [1]
>> p: to path! [f ref]
== f/ref
>> do reduce [p]
== 1
>> p: to path! [f ref:]
== f/ref:
>> do reduce [p]
== 1
>> p: to set-path! [f ref:]
== f/ref::
>> do reduce [p]
== 1
>> p: to set-path! [f ref]
== f/ref:
>> do reduce [p]
== 1
which shows that REBOL is just being very permissive for functions
with refinements.
RPT> I do not think the same. Here the attempt is not set something, but only to
RPT> evaluate the path. If a set-path is by default "set the value referenced by
RPT> the path" this construct should trigger an error or a crash. Obviously this
RPT> can be corrected adding an error! ad hoc, but ist shows for me the interpreter
RPT> behaviour.
I think that for both set-path! and path!, first of all REBOL
determines the value of the first word. Then, it "decodes" the
path up until the last value, and then it decides what to do based
on the type of the path. Probably, as soon as it finds out that
the first word refers to a function!, it passes the control to the
code handling functions, that simply does not "know" about
set-path!s and so behaves like it was a path!.
RPT> Often I'm asking myself: what are advantages of refinements in functions?
Economy of expression. Without refinements, using functions like
OPEN would require a lot of arguments. Also, one could not extend
functions retaining compatibility like it was done with MOLD (/ALL
refinement) or LOAD (/LIBRARY refinement) etc.
Of course, if we had a formal specification for the REBOL language
and the function interpreter, it would be easier to understand
what is a design decision and what is just an implementation
issue.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[21/25] from: rotenca:telvia:it at: 18-Nov-2002 17:50
Hi Ladislav
> Some disadvantages:
>
> 1) the function must test, how it has been called, although that information
> has already been processed to get the arguments
>
> 2) the refinement system works well only if any refinement combination is
> "legal", otherwise the function must check the combination on its own
The 3) problem is confusion with path. The / divisor for function refinements
forces the interpreter to discard all refinement which follow a function call
in a path:
a: func[/b /c][[[1]]]
a/b/c/1/1; == [[1]]
with a different char, for example "!" we could write:
a: func[!b !c][[[1]]]
a!b!c/1/1;== 1
like in
x: [[1]]
x/1/1; == 1
> The main advantage is a lower pollution of the system dictionary.
Only because all loaded local words are added to the global context, but i'm
thinking that this cannot be changed.
---
Ciao
Romano
[22/25] from: rotenca:telvia:it at: 18-Nov-2002 22:40
Hi Gabriele
> I agree with Ladislav.
Gabriele, you bypass Load for this, i was speaking of Load. And my observation
is still valid, also a set-path can be used like a path by the interpreter if
it find a function along the path. Now i'm thinking that the problem is all in
function refinement, see my previous message.
> In particular:
> >> f: func [/ref] [1]
<<quoted lines omitted: 10>>
> >> do reduce [p]
> == 1
This is what i point: no set action at all, the interpreter does not care
about the fact the that path is a set-path!
> >> p: to set-path! [f ref]
> == f/ref:
> >> do reduce [p]
> == 1
> which shows that REBOL is just being very permissive for functions
> with refinements.
At least.
> I think that for both set-path! and path!, first of all REBOL
> determines the value of the first word. Then, it "decodes" the
<<quoted lines omitted: 3>>
> code handling functions, that simply does not "know" about
> set-path!s and so behaves like it was a path!.
Yes you are right and this is what i want to point. I did not want to say that
set-path does not exists in absolute, but that in some situations it is like a
path. I could make an example: a block which, if at some point contains the
word list!, start to behaviour like a list!. Only in this sense i said that it
is not a true datatype!.
> RPT> Often I'm asking myself: what are advantages of refinements in
functions?
> Economy of expression. Without refinements, using functions like
> OPEN would require a lot of arguments.
open: func [file type [integer!]][
if type and 1 [ ;direct]
if type and 2 [ ;no-wait]
if type and 4 [ ;binary]
or
open: func [file type [block!]][
if find type 'direct [ ;direct]
if find type 'no-wait [ ;no-wait]
if find type 'binary [ ;binary]
> Also, one could not extend
> functions retaining compatibility like it was done with MOLD (/ALL
> refinement) or LOAD (/LIBRARY refinement) etc.
You are right. Also because any-type! cannot help for backward compatibility.
---
Ciao
Romano
[23/25] from: g:santilli:tiscalinet:it at: 20-Nov-2002 12:58
Hi Romano,
On Monday, November 18, 2002, 10:40:21 PM, you wrote:
RPT> Yes you are right and this is what i want to point. I did not want to say that
RPT> set-path does not exists in absolute, but that in some situations it is like a
RPT> path. I could make an example: a block which, if at some point contains the
RPT> word list!, start to behaviour like a list!. Only in this sense i said that it
RPT> is not a true datatype!.
One could argue that all any-block! types actually share the same
implementation internally. This doesn't make them one datatype;
parens and blocks differ only in the delimitator, and paths and
set-paths differ only in that set-path! ends with a colon. (REBOL
is so small because most datatypes share the same
implementation...)
RPT> or
RPT> open: func [file type [block!]][
RPT> if find type 'direct [ ;direct]
RPT> if find type 'no-wait [ ;no-wait]
RPT> if find type 'binary [ ;binary]
Basically, any function that requires a lot of optional arguments
would require its own dialect. To make things cleaner, Carl
thought of refinements as a common way that can be used by all the
functions.
Of course, we miss a clean way to propagate refinements, etc.
However, I don't think that your proposal of having:
f: func [] [[[1]]]
f/1 ; == [1]
f/1/1 ; == 1
makes really sense out of this simple example. I would find the
following really unintuitive:
f: func [a b c] [reduce [a b c]]
f/1 1 2 3 ; == 1
f/2 1 2 3 ; == 2
; etc.
(Imagine it when you have less trivial arguments, as in a long
expression.) I would much prefer:
(f 1 2 3)/1
(f 1 2 3)/2
etc.
Anyway, the path notation is just a shortcut notation. When you
can't use paths, you can use PICK and POKE, so there's no real
limitation.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[24/25] from: rotenca:telvia:it at: 20-Nov-2002 19:33
Hi Gabriele
> makes really sense out of this simple example. I would find the
> following really unintuitive:
>
> f: func [a b c] [reduce [a b c]]
>
> f/1 1 2 3 ; == 1
> f/2 1 2 3 ; == 2
> ; etc.
You find it unintuitive because you think at refinement as /word.
If
a: [b 1]
a/b
means:
1) evaluate 'a
2a) if a results in a block, select it with the word 'b
2b) if a results in a object, get in it the word 'b
I should like that this means the exactly same:
a: func [][[b 1]]
a/b
1) evaluate 'a (which, because it is a function, means "execute the body and
return the last value")
2a) if a results in a block, select it with the word 'b
2b) if a results in a object, get in it the word 'b
Instead, because function refinements are = path divisor (only for a choice)
that expression means all another thing:
"evaluate the function and pass /b as a refinement to it."
and before evaluating 'a i can't know what is the right interpretation!
Functions are first class?
> (Imagine it when you have less trivial arguments, as in a long
> expression.) I would much prefer:
>
> (f 1 2 3)/1
> (f 1 2 3)/2
this is indipendent from the previous: can be considered an extension of the
previous to pass arguments to a function (but could be used for compatibility:
a/b ;old interpretation
(a)/b ; my interpretation
(a/d 1)/b ; my interpretation + function refinement + arg
> Anyway, the path notation is just a shortcut notation. When you
> can't use paths, you can use PICK and POKE, so there's no real
> limitation.
yes, you must only decide between
1) Pick, Select, Get In, call a function
2) Poke, Change Find, Set In, call a function
Not so simple...
---
Ciao
Romano
[25/25] from: g:santilli:tiscalinet:it at: 20-Nov-2002 19:53
Hi Romano,
On Wednesday, November 20, 2002, 7:33:46 PM, you wrote:
RPT> You find it unintuitive because you think at refinement as /word.
I find it unintuitive in the case that the function has arguments.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted