Void-safe code syntax suggestion

22 views
Skip to first unread message

Finnian Reilly

unread,
Oct 1, 2017, 10:25:00 AM10/1/17
to Eiffel Users
I offer this suggestion for some future version of the Eiffel language that I think would make void-safe coding constructs clearer. It involves creating an additional use for the `inspect-when' multi-branch construct and introducing a new keyword `detached'. My  idea is best explained by reference to a typical void-safe coding construct taken from the routine `on_mouse_move'' in class EV_GRID_CHOICE_ITEM:

   on_mouse_move (a_x, a_y: INTEGER; a_x_tilt, a_y_tilt, a_pressure: DOUBLE; a_screen_x, a_screen_y: INTEGER)
         
-- Handle mouse moving actions.
     
local
         l_item
: detachable EV_GRID_ITEM
         l_list
: LIST [EV_GRID_ITEM]
     
do
         
if attached choice_list as l_choice_list then
           
if
               
not attached initial_position as l_pos or else
               
(l_pos.x /= l_choice_list.screen_x + a_x and then l_pos.y /= l_choice_list.screen_y + a_y)
           
then
               initial_position
:= Void

               l_item
:= l_choice_list.item_at_virtual_position (l_choice_list.virtual_x_position + a_x,
                  l_choice_list
.virtual_y_position + a_y)
               
if l_item /= Void then
                  l_list
:= l_choice_list.selected_items
                 
if not l_list.is_empty and then l_list.first /= l_item then
                     l_choice_list
.remove_selection
                     l_item
.enable_select
                 
end
                  has_user_selected_item
:= True
               
end
           
end
         
else
            check choice_list
/= Void end
         
end
     
end

Now here is the same code implemented using the proposed syntax:

   on_mouse_move (a_x, a_y: INTEGER; a_x_tilt, a_y_tilt, a_pressure: DOUBLE; a_screen_x, a_screen_y: INTEGER)
         
-- Handle mouse moving actions.
     
local
         l_item
: detachable EV_GRID_ITEM
         l_list
: LIST [EV_GRID_ITEM]
     
do
         inspect choice_list
           
when attached then
               inspect initial_position
                 
when detached or else (initial_position.x /= choice_list.screen_x + a_x
                                         
and then initial_position.y /= choice_list.screen_y + a_y)
                 
then
                     initial_position
:= Void
                     l_item
:= choice_list.item_at_virtual_position (choice_list.virtual_x_position + a_x,
                        choice_list
.virtual_y_position + a_y)
                     inspect l_item
                       
when attached then
                           l_list
:= choice_list.selected_items
                           
if not l_list.is_empty and then l_list.first /= l_item then
                              choice_list
.remove_selection
                              l_item
.enable_select
                           
end
                           has_user_selected_item
:= True
                     
else
                     
end
               
else
               
end
         
else
            check choice_list
/= Void end
         
end
     
end

Before explaining what exactly is achieved by this syntax, I will point out that this syntax is made possible by the fact that the traditional use of `inspect' is only permitted for expressions evaluating to an expanded type (INTEGER or CHARACTER), so the compiler can distinguish the proposed alternate use of `inspect' for detachable variables.

The first thing to notice is that there is no temporary renaming using the `as' keyword, because we have effectively defined a scope starting from "when attached then" until the matching `else', in which it is void-safe to reference the "inspected variable".

The second thing to notice, is that the construct "when detached" defines a scope where the compiler should not permit the referencing of an inspected variable in an expression.

The third thing to notice is that it is permitted to put a boolean expresssion after "when detached or else" that may reference the inspected variable. Admittedly this is something of a departure from the traditional use of `inspect', but I think it prefereable to the "hard to decipher" meaning of

   if
     
not attached initial_position as l_pos or else
     
(l_pos.x /= l_choice_list.screen_x + a_x and then l_pos.y /= l_choice_list.screen_y + a_y)
   
then

READABILITY
If one thinks of this proposed construct as an abbreviated english sentence it makes a lot of sense, for example: inspect (the variable) choice_list (and) when (it is) attached then (do this)

CODE FORMATTING
I have formatted the lines in the traditional way for inspect multi-branches, but because of the binary nature it could be formatted more like an "if then else" conditional, by pulling the "when attached" on to the same line as the `inspect' keyword, and formatting accordingly:
   on_mouse_move (a_x, a_y: INTEGER; a_x_tilt, a_y_tilt, a_pressure: DOUBLE; a_screen_x, a_screen_y: INTEGER)
         
-- Handle mouse moving actions.
     
local
         l_item
: detachable EV_GRID_ITEM
         l_list
: LIST [EV_GRID_ITEM]
     
do
         inspect choice_list
when attached then
            inspect initial_position
when detached
               
or else (initial_position.x /= choice_list.screen_x + a_x
                         
and then initial_position.y /= choice_list.screen_y + a_y)
           
then
               initial_position
:= Void
               l_item
:= choice_list.item_at_virtual_position (choice_list.virtual_x_position + a_x,
                  choice_list
.virtual_y_position + a_y)
               inspect l_item
when attached then
                  l_list
:= choice_list.selected_items
                 
if not l_list.is_empty and then l_list.first /= l_item then
                     choice_list
.remove_selection
                     l_item
.enable_select
                 
end
                  has_user_selected_item
:= True
               
else
               
end
           
else
           
end
         
else
            check choice_list
/= Void end
         
end
     
end



Colin Adams

unread,
Oct 1, 2017, 10:34:36 AM10/1/17
to Eiffel Users
Not worth a new keyword IMHO.

--
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.

Woland's Cat

unread,
Oct 1, 2017, 10:39:06 AM10/1/17
to eiffel...@googlegroups.com

I disagree - I think it's a good suggestion. I don't care that much
about the keyword count. I do care about clarity, and I find the if
attached x as att_x then pattern very clunky.

- thomas

Finnian Reilly

unread,
Oct 1, 2017, 10:43:42 AM10/1/17
to Eiffel Users

Come to think of it, since "if then" conditionals are not required to have `else' keyword, we could make the closing `else' optional for this alternate use of `inspect' as well. So our example code would look like this:
   on_mouse_move (a_x, a_y: INTEGER; a_x_tilt, a_y_tilt, a_pressure: DOUBLE; a_screen_x, a_screen_y: INTEGER)
         
-- Handle mouse moving actions.
     
local
         l_item
: detachable EV_GRID_ITEM
         l_list
: LIST [EV_GRID_ITEM]
     
do
         inspect choice_list
when attached then
            inspect initial_position
when detached
               
or else (initial_position.x /= choice_list.screen_x + a_x
                         
and then initial_position.y /= choice_list.screen_y + a_y)
           
then
               initial_position
:= Void
               l_item
:= choice_list.item_at_virtual_position (choice_list.virtual_x_position + a_x,
                  choice_list
.virtual_y_position + a_y)
               inspect l_item
when attached then
                  l_list
:= choice_list.selected_items
                 
if not l_list.is_empty and then l_list.first /= l_item then
                     choice_list
.remove_selection
                     l_item
.enable_select
                 
end
                  has_user_selected_item
:= True

Finnian Reilly

unread,
Oct 1, 2017, 10:53:16 AM10/1/17
to Eiffel Users
The basic idea is not dependent on having any new keywords. If most people don't like `detached' we can make do with "when not attached", but as Eiffel already has so many keywords, we may as well be "hung for a sheep as a lamb" as the saying goes.

Eric Bezault

unread,
Oct 1, 2017, 1:54:09 PM10/1/17
to eiffel...@googlegroups.com, Finnian Reilly
On 10/1/2017 16:25, Finnian Reilly wrote:
> Before explaining what exactly is achieved by this syntax, I will point
> out that this syntax is made possible by the fact that the traditional
> use of `inspect' is only permitted for expressions evaluating to an
> expanded type (INTEGER or CHARACTER), so the compiler can distinguish
> the proposed alternate use of `inspect' for detachable variables.

I think that the ECMA standard accepts STRING in addition to INTEGER
and CHARACTER.

> The first thing to notice is that there is no temporary renaming using
> the `as' keyword, because we have effectively defined a scope starting
> from "when attached then" until the matching `else', in which it is
> void-safe to reference the "inspected variable".

When we have:

if attached foo then
....
end

the scope is well defined as well. The reason why we use
'as' is because if `foo' is a function, it may well return
different values (possibly void) between the time we first
evaluated it in the boolean expression of the if-instruction
and the time we evaluate it again in the body. Let me try
to make it clearer, using your inspect construct this time:

foo: detachable STRING
do
if not foo_already_called then
Result := "OK"
foo_already_called := True
else
Result := Void
end
end

inspect foo <- first call, not void
when attached then
foo.do_something <- second call, void
end

Yes, this example violates CQS, but I hope it nevertheless
makes it easier to understand the problem.

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

gerrit.leder

unread,
Oct 4, 2017, 7:15:16 AM10/4/17
to Eiffel Users
I have followed some discussion of Kotlin language, where they describe the nullable type with an appended question mark:

    ###Null
    In Kotlin you have to decide whether a variable can be assigned null or not. This applies to both primitives or class types.
    A nullable variable is marked by assigning ? after the type, e.g. var firstName: String?

Finnian Reilly

unread,
Oct 4, 2017, 7:39:58 AM10/4/17
to Eiffel Users


On Wednesday, 4 October 2017 12:15:16 UTC+1, gerrit.leder wrote:
I have followed some discussion of Kotlin language, where they describe the nullable type with an appended question mark:

    ###Null
    In Kotlin you have to decide whether a variable can be assigned null or not. This applies to both primitives or class types.
    A nullable variable is marked by assigning ? after the type, e.g. var firstName: String?
 
in Eiffel this would be the same as
firstName: detachable STRING

That would seem to imply that all variables are attached by default in Kotlin. So what happens if you declare

var firstName: String

and then never initialize it. Does it call implicitly a default creation routine? Or does the compiler give you an error if you never assign a value?

gerrit.leder

unread,
Oct 4, 2017, 7:47:49 AM10/4/17
to Eiffel Users
I think this code snippet would be a test example, if you do not assign "Adam" in the first place:

fun main(args : Array<String>) { 
    val firstName : String = "Adam"
    val name : String? = firstName 
    print("$name") 
}

I can try out, on the weekend, if the compiler gives an error or "firstName" is initialized by default...

Am Sonntag, 1. Oktober 2017 16:25:00 UTC+2 schrieb Finnian Reilly:

Alexander Kogtenkov

unread,
Oct 4, 2017, 7:50:08 AM10/4/17
to eiffel...@googlegroups.com
Kotlin does require that all fields of non-null types are initialized. However, it does not prevent from using a reference to the current object before all fields are initialized. As a result, one can easily get a NullPointerException in pure Kotlin. In other words, its null-safety is unsound: it does not guarantee absence of NullPointerException errors at run-time.

The syntax with question and exclamation marks was used in Eiffel at the early days of void safety. Then the symbols were replaced with keywords to be in line with Eiffel tradition to prefer keywords over symbols and to make the type annotations more visible.

Alexander Kogtenkov


Finnian Reilly <frei...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages