Current rules on attachment - consistent?

30 views
Skip to first unread message

Thomas Beale

unread,
Feb 22, 2018, 7:52:02 AM2/22/18
to Eiffel Users
As of a release or two ago, I can change code like this:

if attached my_thing as att_my_thing then
    do_x
(att_my_thing)
end

into:

if attached my_thing then
    do_x
(my_thing) -- where do_x expects an attached T
end


But it appears I cannot change the following expression:

 attached arch_node as a_n and then (attached parent.arch_node as parent_a_n and then parent_a_n.attributes.has (a_n))

into:

 attached arch_node and then (attached parent.arch_node and then parent.arch_node.attributes.has (arch_node))

even though the implied decision tree is of the same form as the previous example - i.e., what is to the right of 'and then' must be predicated on the truth of the precedent.

Is there any reason for this?

- thomas

Eric Bezault

unread,
Feb 22, 2018, 7:58:07 AM2/22/18
to eiffel...@googlegroups.com, Thomas Beale
Could it be that `my_thing' is a formal argument or a
local variable, and `arch_node' is an attribute or
a function? This would explain EiffelStudio's behavior.

--
Eric Bezault
mailto:er...@gobosoft.com
http://www.gobosoft.com



On 2/22/2018 13:52, Thomas Beale wrote:
> As of a release or two ago, I can change code like this:
>
> |
> ifattached my_thing asatt_my_thing then
>     do_x (att_my_thing)
> end
> |
>
> into:
>
> |
> ifattached my_thing then
>     do_x (my_thing)--wheredo_x expects an attached T
> end
> |
>
>
> But it appears I cannot change the following expression:
>
> |
>  attached arch_node asa_n andthen(attached parent.arch_node
> asparent_a_n andthenparent_a_n.attributes.has (a_n))
> |
>
> into:
>
> |
>  attached arch_node andthen(attached parent.arch_node
> andthenparent.arch_node.attributes.has (arch_node))

Thomas Beale

unread,
Feb 22, 2018, 8:04:59 AM2/22/18
to Eiffel Users
my_thing in my real code is a detachable class attribute.

Colin Adams

unread,
Feb 22, 2018, 8:09:00 AM2/22/18
to eiffel...@googlegroups.com
Does your ECF say no concurrency?

--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.
Visit this group at https://groups.google.com/group/eiffel-users.
For more options, visit https://groups.google.com/d/optout.

Thomas Beale

unread,
Feb 22, 2018, 8:11:19 AM2/22/18
to Eiffel Users
It is set to 'thread'.

Colin Adams

unread,
Feb 22, 2018, 8:15:46 AM2/22/18
to eiffel...@googlegroups.com
That's odd then, because the whole rationale for treating attributes differently from formal arguments is for a thread context switch. If it was only allowed for no concurrency, I could have understood it (although it would not be a good idea, as the source code can not control the ECF settings).

Eric Bezault

unread,
Feb 22, 2018, 8:41:38 AM2/22/18
to eiffel...@googlegroups.com, Thomas Beale
On 2/22/2018 14:04, Thomas Beale wrote:
> my_thing in my real code is a detachable class attribute.

I assume that `do_x' expects an attached type, right?

So, the other thing that I can think of is that one
is about passing an argument, whereas in the second one
there is also a qualified call with a target. So it
could be that your void-safety setting is not "all"
but some intermediate state.

--
Eric Bezault
mailto:er...@gobosoft.com
http://www.gobosoft.com


>
> On Thursday, 22 February 2018 12:58:07 UTC, Eric Bezault wrote:
>
> Could it be that `my_thing' is a formal argument or a
> local variable, and `arch_node' is an attribute or
> a function? This would explain EiffelStudio's behavior.
>
> --
> Eric Bezault
> mailto:er...@gobosoft.com <javascript:>

Rosivaldo Fernandes Alves

unread,
Mar 5, 2018, 7:06:49 AM3/5/18
to eiffel...@googlegroups.com
I'm far from being an expert, but could you have a look at the rationale
below?


attached
arch_node as a_n
-- If `arch_node' is attached, `a_n' gets attached to the same object.

and then (
attached
parent.arch_node as parent_a_n
-- If `parent.arch_node' is attached, `parent_a_n' gets attached
to the same object.

and then
parent_a_n.
-- Since `parent_a_n' is local, it can't have been detached
since its attachment.

attributes.has
(a_n)
-- Since `a_n' is local, it can't have been detached since its
attachment.

)


attached
arch_node
-- Yes, `arch_node' is attached, but unless it is local, who knows
about its future in a concurrent environment?

and then (
attached
parent.arch_node
-- Yes, `parent'.`arch_node' is attached, but IT IS NOT
LOCAL(!); who knows about its future in a concurrent environment?

and then
parent.arch_node.
-- Since `parent'.`arch_node' IS NOT LOCAL, it may have got
detached since the test above.

attributes.has (arch_node)
-- Unless`arch_node' IS LOCAL, it may have got detached since
the test above.

)


Best regards,

Rosivaldo.

Em 22/02/2018 09:52, Thomas Beale escreveu:
> As of a release or two ago, I can change code like this:
>
> (...)

Thomas Beale

unread,
Mar 30, 2018, 8:14:56 AM3/30/18
to Eiffel Users
Having read the replies and remembered the fact that passing a reference to a call is going to implicate threading / separate processing, I have a simpler example which generates a VEVI, which I do not understand:
all_ancestors: ARRAYED_SET [STRING]
-- list of all inheritance parent class names (upper case)
do
if attached all_ancestors_cache then
Result := all_ancestors_cache
else
create Result.make (0)
Result.compare_objects
across ancestors as ancestors_csr loop
Result.extend (ancestors_csr.key)
Result.merge (ancestors_csr.item.all_ancestors)
end
all_ancestors_cache := Result
end
ensure
strict: not Result.has (name.as_upper)
end


The error is the usual VEVI: Result not set. I can't see how this is arrived at.

- thomas

Colin Adams

unread,
Mar 30, 2018, 8:26:19 AM3/30/18
to eiffel...@googlegroups.com
I think you need:

if attached all_ancestors_cache as l_cache then
  Result := l_cache

--

Woland's Cat

unread,
Mar 30, 2018, 8:42:01 AM3/30/18
to eiffel...@googlegroups.com
On 30/03/2018 13:26, Colin Adams wrote:
I think you need:

if attached all_ancestors_cache as l_cache then
  Result := l_cache

well that was my original point - you can now take out ?most? of that kind of code and just do:

if attached some_x then
    -- simple expression with some_x, but no calls
end

I've done this in a lot of code as I come across it (certainly improves readability), but I cannot work out what rules the compiler is using for this.

- thomas


--
Thomas Beale
Principal, Ars Semantica
Consultant, ABD Team, Intermountain Healthcare
Management Board, Specifications Program Lead, openEHR Foundation
Chartered IT Professional Fellow, BCS, British Computer Society
Health IT blog | Culture blog

Alexander Kogtenkov

unread,
Mar 30, 2018, 8:42:18 AM3/30/18
to eiffel...@googlegroups.com
Hi Thomas,

I believe "all_ancestors_cache" is an attribute that in a multi-threaded environment can be set to Void by another thread. That's why checking it for void does not guarantee it will not become Void inside "then" branch. One solution is to mark the attribute as stable. The restriction for a stable attribute is that it can be assigned only an attached value. This ensures that even in a multi-threaded environment, if the attribute is not void at some point, it will never become void afterwards (regardless of any other thread assigning a value to it). Then your code should compile unchanged.

If you do not want to mark the attribute as stable, the following code should work (assuming you are using a recent version of EiffelStudio):

   Result := all_ancestors_cache
   if not attached Result then
      ... -- The code taken from "else" branch of the original example.
   end

Best regards,
Alexander Kogtenkov


Thomas Beale <wolan...@gmail.com>:

Thomas Beale

unread,
Mar 30, 2018, 8:48:14 AM3/30/18
to Eiffel Users
Ok that makes sense... I now vaguely remember this rule. I had mentally ignored the 'stable' settings on many of my attributes. For 'cache' attributes, they need to be resettable to Void, so the code pattern you suggested applies - indeed this is the standard default way of coding this, which I changed across my code base due to recommendations a few years ago when void-safety was introduced. 

At least the overall noise factor from void-safety is finally going down...!

- thomas
Reply all
Reply to author
Forward
0 new messages