[squeak-dev] [Question] nil, true, false in array literals

James Foster Smalltalk at JGFoster.net
Wed Dec 3 18:59:07 UTC 2008


On Dec 3, 2008, at 6:37 PM, Igor Stasenko wrote:

> 2008/12/3 James Foster <Smalltalk at jgfoster.net>:
>>
>> On Dec 3, 2008, at 4:57 PM, Igor Stasenko wrote:
>>
>>> 2008/12/3 James Foster <Smalltalk at jgfoster.net>:
>>>>
>>>> Igor,
>>>>
>>>> What would you expect from the following: #(1)? Should it be  
>>>> (Array with:
>>>> 1)
>>>> or (Array with: #'1')?
>>
>> You didn't answer my question!
>
> see end of this message.

If I understand correctly, you want #(1) to be (Array with: 1). Please  
correct me if I'm wrong.

>>>> I think that the assumption is that you should be able to include  
>>>> any
>>>> literal constant (including SmallIntegers) in a literal constant  
>>>> array. I
>>>> think of #(foo) as a shortcut for #(#'foo'), where the second  
>>>> form is
>>>> more
>>>> explicit. If you want to avoid the ambiguity, then always be  
>>>> explicit
>>>> when
>>>> you want a symbol.
>>>
>>> Well, the point is, that i look differently at such names. I don't
>>> treat them as literal constants, but as names which globally bound  
>>> to
>>> some object.
>>
>> If you are using the Smalltalk syntax of #(), then you should learn  
>> to look
>> at true, false, and nil as literal constants, because that is what  
>> the
>> language definition specifies.
>
> if you so sure, can you please give me a citation where it explicitly
> says about it? Reasoning?

As you cited, ANSI 3.4.6.6 defines Array Literals to support three  
reserved identifiers.

> Doesn't smalltalk stands for simplicity?

Yes, I think so. It might have been better if Smalltalk did not treat  
other identifiers as Symbols. If you want a Symbol in an Array  
Literal, make it explicit.

> What is simpler to remember:
> - a name found in literal array treated as symbolic literal
> - a name found in literal array treated as symbolic literal , except
> nil, true, false
> ?

I assume that this is a rhetorical question where the expected answer  
is option #1. If you are aiming for the simplest thing, you could just  
have the rule:
- a token that the compiler identifies as a literal (String, Symbol,  
Number, Character)
If we are going to allow names as well, then we have two simple  
choices: (1) treat the name as a Symbol (giving two ways of specifying  
the same thing); or (2) treat the name as an identifier to well-known  
constants. I understand that you would prefer #1 while I would prefer  
#2 since it adds capability. It seems that most implementations take a  
third, more complex approach: (3) allow names as well-known constants  
(true/false/nil), otherwise treat as a Symbol. I agree that option 3  
is more complex. If I were implementing a Smalltalk, I'd be tempted to  
go with #2, and treat other names as errors.

>>> And i can explain why.
>>> Suppose i want to introduce a class(es) to work with ternary logic:
>>> 'true' 'false' 'unknown' .. or whatever.
>>> Does it makes an 'unknown' name less privileged than 'true' or
>>> 'false'? So, what do you do in this case? Introduce a new 'literal
>>> constant'? Otherwise you'll have an issue with #(true false  
>>> unknown) .
>>
>> Do you want #(true false unknown) to return three symbols? If so,  
>> then be
>> explicit: #(#'true' #'false' #'unknown').
>
> at least it would be more uniform from parser's POV, to not make
> exceptions for these three cases,
> as well as simpler to remember.

I agree that not have an exception would be easier for the parser, but  
I disagree about what is the exception. The exception is not for the  
three defined names, the exception is an undefined name. They could be  
treated as an error or they could be treated as a Symbol.

>> If you would like an Array constructor that evaluates expressions  
>> at compile
>> time, then use a different language syntax. In Squeak, you may use  
>> the
>> following:
>>       {true. false. unknown}
>> If 'unknown' is bound to an object, then it will work, otherwise  
>> you will
>> get a compile error.
>>
> sure i can do that. But this is OT.

I don't think so. You are arguing for extending Array Literals and I'm  
offering an alternative so that you don't have to make Array Literals  
more complex.

>>> Another variant and same question: Some of us using a Null class to
>>> make use of message eating nulls.
>>> Now, if i want to return null, can i introduce a 'literal constant'
>>> named 'null' as well?
>>
>> Not without changing the language.
>>
>>> Or, what makes 'null' less important (for someone) than 'nil'. A
>>> little bit of discrimination :)
>>
>> 'null' is less important than 'nil' because 'null' is not part of the
>> language.
>
> good point, as for orthodox, but not for me.
> An earth is flat, because church says so, any other opinion is  
> herecy :).

I consider language definition to be a type of orthodoxy. If you want  
a different orthodoxy, then you have a different religion/language. I  
don't mind a Reformation now and then, just don't call the Pope the  
Anti-Christ and claim to be Catholic. ;-)

>>> Another guys can come and say: hey, i'm a matematician, and i want a
>>> 'literal constant' named 'epsilon' , so lets modify compiler to
>>> resolve it as a sole instance of Epsilon class.
>>
>> Even easier would be to have a 'global constant' named 'epsilon':
>>       Smalltalk at: #'epsilon' put: Epsilon new.
>>
>
> sure, but i don't see the strong reason why same not applied to 'nil',
> 'true' , 'false' as well.

In GemStone, true, false, and nil are actual entries in a  
SymbolDictionary!

>>> So, how many of such 'literal constants' we may need in future?
>>
>> None. The ones defined by the language are enough.
>
> A very subjective point of view :)

Sure, but I'm entitled to my opinion!

>>> Or
>>> maybe, if we treat such names as globals, then we won't need to hack
>>> the compiler every time?
>>
>> To treat something as a global, add it to Smalltalk, and the  
>> compiler will
>> find it. No compiler hacking involved.
>>
>>> And then, obviously #(true false nil) = (Array with: #true with:
>>> #false with: #nil)
>>
>> Again, are you expecting #(1 2) = (Array with: #'1' with: #'2')?  
>> That would
>> probably surprise a lot of people and break much existing code.
>>
>
> no, i'm not asserting about the constants like numbers or strings or
> symbol literals prepended with '#' because
> they are not ambiguous and always mean same regardless the context (be
> it in #() or in method body).

But it is ambiguous. What if I wanted #(2) to be the same as (Array  
with: 2 asString asSymbol)? The compiler defines 2 by itself as an  
Integer. The compiler defines nil by itself as a reference to a  
singleton, not as a Symbol. Why should we treat nil differently from  
2? Inside a literal array, we get the thing the compiler would give us.

>>>> James
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko AKA sig.
>>
>> James
>>
>
> -- 
> Best regards,
> Igor Stasenko AKA sig.
>
>




More information about the Squeak-dev mailing list