||

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
68 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

Re: ||

Ben Coman


On Sun, Feb 8, 2015 at 4:55 AM, Hernán Morales Durand <[hidden email]> wrote:

How can I halt the execution of a specific pragma? Can I write <myPragma halt>?


In following this discussion, this thought also occurred to me.  It would be nice to be able to break at the point where the pragma is being collected.  As well as helping determine if the pragma is working, this would help discoverability of how pragmas work.

cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: ||

Eliot Miranda-2
In reply to this post by hernanmd
Hi Hernan,


On Feb 7, 2015, at 12:55 PM, Hernán Morales Durand <[hidden email]> wrote:

Hi Eliot,

2015-02-07 14:48 GMT-03:00 Eliot Miranda <[hidden email]>:
Hi Hernan,

On Sat, Feb 7, 2015 at 7:41 AM, Hernán Morales Durand <[hidden email]> wrote:

2015-02-07 5:59 GMT-03:00 kilon alios <[hidden email]>:
Personally I don't like Pragmas, they have not convinced me so far that they fit the style of Smalltalk syntax. I have to confess though I never liked descriptive elements and languages . 


Me neither. Actually the pragma idea is not wrong per se, it is the tag syntax to write them which bothers me. Because the world can be described with tags if you start that path.

How exactly is the syntax wrong?

I am not saying syntax is wrong, I just don't like it because:

1) Adds another level of representation inside an already reflective system.

What do you mean exactly?  I don't have clear recollection of whether they were in Squeak in 08 or if I ported then, but at that time CompiledMethod had a properties object, and pragmas were merged into this.  What I did do was save a lot of space getting rid if the properties object unless a method needed it.  And IIRC I changed the implementing class from MethodProperties to AdditionalMethodState.  So there was no additional level of representation.  a) the syntax was already there fir primitives and b) the state was already there in methods.

2) It could be done with plain common message sends.

No it can't.  Common sends are executable and we don't want pragmas executed when the method is run, we want the pragma executed when the method is added, or analysed.  That was what was ugly about the use of plain sends in e.f. VMMaker, that there had to be lots of empty implementations of the messages used for metadata.  

So using normal sends
- prevents the metadata from being directly executed because executing them when the method is run is wrong 
- confuses meta level and normal level, putting them at the same level, and hence...
- confusing for the programmer because its not obvious what's metadata and what's a normal send
- makes analysis harder for the same reason

3) Should be (to me) "hidden" from method pane, and displayed by a specific tool inside the system browser.

I disagree.  I want to see the pragma.  It has essential information that shouldn't be hidden.  I want to edit it easily.  And how can you in the one hand say it can be implemented as a normal message send a d at the same time want it hidden?  Be consistent :-)

 
The <literalMessagePattern> syntax predates pragmas.  It was used first for numeric primitives in Smalltalk-76 or Smalltalk-80.  Squeak extended it with primitive:module:.  I and others extended it to include arbitrary literal message patterns.  The syntax of a literal message pattern is the syntax of a send with no receiver and only literal arguments. 
The use of this syntax means
a) no new syntax
b) each pragma is potentially executable
c) methods using specific pragmas can be found using "find senders"
d) the execution side of a pragma can be found using "find implementors"

So what's wrong with that?  How is it wrong to use a common Smalltalk object, a Message, that is well-supported in the system, for method metadata?


I get that pragmas are messages, but they assume an implicit receiver, which actually depends on context. If I understood right with pragmas always receiver = destination?

Not for pragmas that are just labels.  And what's destination?  In the menu building example above the destination"is the menu but the receiver is the menu builder.  So I think that what the receiver is depends on usage.

  If you change things in the communication model (receiver, sender, message, etc.), by removing or adding elements, you have a loss in the message because it gets harder to reconstruct the message send.

I don't understand this.  Can you expand?


Consider

<eventRegistration>
| eventRegistration |
{ eventRegistration }.
self eventRegistration.

which of them "it sounds like" you cannot infer their purpose?

I don't get the example, because of the confusion of meta layers.

<eventRegistration>
says "this is metadata"

| eventRegistration |

says "this is a bug in the method because the variable isn't used, and eg Opal will remove it so it won't be there".

{ eventRegistration }.
I guess you mean { #eventRegistration }.  If so this is the same.  An optimizing compiler will delete it.

self eventRegistration.
says "send myself eventRegustration".  Which /isn't/ what's wanted.

So for me only the pragma implies "this method is to be registered with the event system".  The middle two say "I am a bug, or syntax error".  The last one says "I am a normal send".



To me the first because you need the context MyClass>>methodName
and you need to browse the pragma to get its purpose.


 
There are other ways to add metadata to methods. Without tagging.

Haven't we discussed that?  Putting metadata off to the side introduces a bookkeeping problem.  It is a bad idea.

Yes, but I still have a lot of doubts about feedback with pragmas (I hope you view them as constructive criticism).

I'm finding this whole conversation exhausting.  

Is like pragmas assume there is always a perfect message transaction.
How can I halt the execution of a specific pragma?

By putting a break point in its implementations.

Can I write <myPragma halt>?

No.  But you can out a conditional breakpoint in CompiledMethod>>pragmaAt: or in the pragma's implementation.

How do I know if it will get executed?

By reading the broader system or adding break pints as just described.

Is <shortcut> a functional pragma?
How do I distinguis any pragma from being functional or "documentation"?

Using "implementors" and "senders" you can find out where it may be used.  One if the problems of late-bound systems is figuring out what binds to what.  Pragmas are more difficult to figure out unless pragmas have clearly commented implementations.

 
 
And they don't need to be in the method pane itself.

For some kinds of metadata, for metadata with semantics, not just a documentary function, it is important for the metadata to be obvious. 

I think this depends on context. Because your work could be towards low-level machinery details or software reenginering, doesn't mean that we all need to view compiler directives, functional and structural annotations, etc.

That's a mischaracterisation.  Most of their uses are for pluggable GUIs.  And if this is so onerous why weren't you protesting <primitive: 123>?


And if I can write some prediction... When someone invents automatic annotation (like happens now with genomes) and decides it will be cool to have them in the image (because you will gain performance, more reflective capabilitites, etc) methods could explode with pragmas to the point gets to be annoying to browse any method. Then the tool will have to be built by need.
 
No one has argued for hiding the primitive specification off-to-the-side.  "Need" is a poor criticism here because using turing equivalence lots of things don't "need" to be the way they are.  Instead why not ask what are the pros and cons?


Ok, many of us knows the pros. I have been using pragmas for a while.
But if we stop discussing then it will never adapt to new ideas.
So you may want to share your view of cons too :)

The cons are that for years, and at length, one has to defend a good idea ;-).  Pragmas were a new idea and here in thus conversation we see how resistant we are to new ideas.  I've seen nothing against the need for per-method metadata and a lot on how it can be done with other mechanisms.  But the existing mechanisms don't do one of two things
- separate normal from meta levels
- obviously associate metadata with methods.

So what I'm missing in this conversation is addressing the issues:
- how in a componentised loadable system do we decouple component loads where components collide in areas like global menu definitions, inspectors, etc?
- how do we associate metadata with methods so that 
   - the metadata is of a form that fits well with the host system?
   - the metadata is clearly associated with the method it is data of?
   - the bookkeeping is managed?

You could add good questions here.  But these are the questions I was thinking of when we added pragmas to VW.


It is like having to specify protocol because there is no list pane to create them.

I disagree.  When the pragma is specifying type information, specifying that the method is an action on a specific menu, is a pane in an inspector, and many other uses, it is essential that that information be represented, and putting it in a one-off bookkeeping system is a bad idea.  We're not talking about simple documentary metadata like author, category etc. 

Well, I think documentary metadata is tremendously complex.
 
We're using pragmas for semantics, semantics of the method that are outside of its execution semantics, semantics about how the method fits in the broader system.  And putting that in non-obvious places is a bad idea.  


I agree. But obvious could be a place where can be located by a method though not necessarily visible.

Cheers,

Hernán

 


Hernán
 
About python decorators I disagree that are similar to pragmas. Pragmas are focused on being descriptive , python decorators are descriptive as by product. The main focus of python decorators is to shorten code by introducing syntactic sugar. 

Kilon, pragmas are not limited to being descriptive.
 

I agree though this is a very interesting discussion and I dont understand most of the things stated here so I leave an open door and mind for pragmas. Maybe one day I will "get it". 

That would be nice :) 



 

On Sat, Feb 7, 2015 at 10:02 AM, Thierry Goubier <[hidden email]> wrote:


2015-02-06 22:00 GMT+01:00 stepharo <[hidden email]>:
Really interesting discussion. I like pragmas but this is interesting to see them challenged.

Thanks. It's a pleasure to discuss that way :)
 
Yes, but there end up being lots of naming conventions and they are non-obvious.  Whereas pragmas, because they are in-your-face in the methods in question, don't need conventions. They just need documenting ;-).
Thierry I'm skeptical that multiple protocol will save the problem because you will rely on coding conventions.

Pragma as well: just explain the conventions behind the gtInspector pragmas, for example.

But give me multiple protocols and I'll show you the same conventions rewritten in less lines (and a slightly more efficient code).
 
And pragma is a clever tagging.

Then maybe we should remove protocols and replace them with pragmas :)

Thierry
 

Stef








--
best,
Eliot

Reply | Threaded
Open this post in threaded view
|

Re: ||

kilon.alios

"I disagree.  I want to see the pragma.  It has essential information that shouldn't be hidden.  I want to edit it easily.  And how can you in the one hand say it can be implemented as a normal message send a d at the same time want it hidden?  Be consistent :-)"

I agree with you Eliot, I definitely would not want for pragmas to be hidden. They are an important part of the code they should be visible with the rest of the code. It would lead to confusion otherwise . Opening 10 tools to be able to view code is also not ideal.  
Reply | Threaded
Open this post in threaded view
|

Re: ||

hernanmd
In reply to this post by Eliot Miranda-2
Hi Eliot,

2015-02-08 12:50 GMT-03:00 Eliot Miranda <[hidden email]>:
Hi Hernan,


On Feb 7, 2015, at 12:55 PM, Hernán Morales Durand <[hidden email]> wrote:

Hi Eliot,

2015-02-07 14:48 GMT-03:00 Eliot Miranda <[hidden email]>:
Hi Hernan,

On Sat, Feb 7, 2015 at 7:41 AM, Hernán Morales Durand <[hidden email]> wrote:

2015-02-07 5:59 GMT-03:00 kilon alios <[hidden email]>:
Personally I don't like Pragmas, they have not convinced me so far that they fit the style of Smalltalk syntax. I have to confess though I never liked descriptive elements and languages . 


Me neither. Actually the pragma idea is not wrong per se, it is the tag syntax to write them which bothers me. Because the world can be described with tags if you start that path.

How exactly is the syntax wrong?

I am not saying syntax is wrong, I just don't like it because:

1) Adds another level of representation inside an already reflective system.

What do you mean exactly?  I don't have clear recollection of whether they were in Squeak in 08 or if I ported then, but at that time CompiledMethod had a properties object, and pragmas were merged into this.  What I did do was save a lot of space getting rid if the properties object unless a method needed it.  And IIRC I changed the implementing class from MethodProperties to AdditionalMethodState.  So there was no additional level of representation.  a) the syntax was already there fir primitives and b) the state was already there in methods.


The place where pragmas are located internally are not an issue for me. The fact that special tags are not following the message pattern template is. It says there is a special collector, parser, validator, etc. a whole mechanism because something is - supposedly - not easily expressible with plain reflective messages.

2) It could be done with plain common message sends.

No it can't. Common sends are executable and we don't want pragmas executed when the method is run, we want the pragma executed when the method is added, or analysed. That was what was ugly about the use of plain sends in e.f. VMMaker, that there had to be lots of empty implementations of the messages used for metadata.  

So using normal sends
- prevents the metadata from being directly executed because executing them when the method is run is wrong 
- confuses meta level and normal level, putting them at the same level, and hence...
- confusing for the programmer because its not obvious what's metadata and what's a normal send
- makes analysis harder for the same reason


We are talking about different worlds here.
Theoretically I could mark methods this way:

(Pragma
    for: (ASTBlockClosure >> #value:)
    selector: #primitive:
    arguments: (Array with: 60)) addPragma.

So the annotations could be written with normal message sends.
And they could be tool supported, so no one gets confused.
 
3) Should be (to me) "hidden" from method pane, and displayed by a specific tool inside the system browser.

I disagree.  I want to see the pragma.  It has essential information that shouldn't be hidden.  I want to edit it easily.  

I want to see and edit the pragma too, when I am really interested. Just like with the bytecodes.
 
And how can you in the one hand say it can be implemented as a normal message send a d at the same time want it hidden?  Be consistent :-)


There is no inconsistency. I am saying they should be hidden from the method body.

The method pane you see in the browser should be used to send messages to your modeling domain (which already imposes its own difficulty), not being exploited to add meta information where meta could belong to instrumentation analysis (lint, profiling) or UI building (keymap, menu) or whatever excuse found to add more tags.

I wonder how one could refactor this method:

Greetings>>helloWorld
    <year: 2015>
    <status: #toDo>
    <author: 'Hernán'>
    <scope: #private>

    <soapOperationName: #HelloWorld>
    <soapDocumentation: #'Returns Hello World'>
    <soapResult: #String>
    <soapStyle: #RPC>

    <rmiOperationName: #HelloWorld>
    <rmiDocumentation: #'Returns Hello World'>
    <rmiResult: #String>
   
    <asn1OperationName: #HelloWorld>
    <asn1Documentation: #'Returns Hello World'>
    <asn1Result: #UTF8String>
   
    <dcomOperationName: #HelloWorld>
    <dcomDocumentation: #'Returns Hello World'>
    <dcomResult: #String>
   
    ^'Hello World'


 
The <literalMessagePattern> syntax predates pragmas.  It was used first for numeric primitives in Smalltalk-76 or Smalltalk-80.  Squeak extended it with primitive:module:.  I and others extended it to include arbitrary literal message patterns.  The syntax of a literal message pattern is the syntax of a send with no receiver and only literal arguments. 
The use of this syntax means
a) no new syntax
b) each pragma is potentially executable
c) methods using specific pragmas can be found using "find senders"
d) the execution side of a pragma can be found using "find implementors"

So what's wrong with that?  How is it wrong to use a common Smalltalk object, a Message, that is well-supported in the system, for method metadata?


I get that pragmas are messages, but they assume an implicit receiver, which actually depends on context. If I understood right with pragmas always receiver = destination?

Not for pragmas that are just labels.  And what's destination?  In the menu building example above the destination"is the menu but the receiver is the menu builder.  So I think that what the receiver is depends on usage.

  If you change things in the communication model (receiver, sender, message, etc.), by removing or adding elements, you have a loss in the message because it gets harder to reconstruct the message send.

I don't understand this.  Can you expand?


Now I realize how far we are from understanding. But I start to feel tired to write about communication models here.
 

Consider

<eventRegistration>
| eventRegistration |
{ eventRegistration }.
self eventRegistration.

which of them "it sounds like" you cannot infer their purpose?

I don't get the example, because of the confusion of meta layers.


Now you understand me :)
 
<eventRegistration>
says "this is metadata"


yes, but not what type of metadata is. Is metadata for instrumentation? is for documentation?
 
| eventRegistration |

says "this is a bug in the method because the variable isn't used, and eg Opal will remove it so it won't be there".


but you get this is a local variable supposed to be used in the current method. You can get the scope easily.

 
{ eventRegistration }.
I guess you mean { #eventRegistration }.  If so this is the same.  An optimizing compiler will delete it.


Yes. The idea there is the same, you would associate the eventRegistration as an Array element to be accessed in the current method for example.
 
self eventRegistration.
says "send myself eventRegustration".  Which /isn't/ what's wanted.

So for me only the pragma implies "this method is to be registered with the event system".  The middle two say "I am a bug, or syntax error".  The last one says "I am a normal send".


To me says "this method contains code which defines an event". Where the event is defined should need more metadata until explicit semantics are enough complete. 


To me the first because you need the context MyClass>>methodName
and you need to browse the pragma to get its purpose.


 
There are other ways to add metadata to methods. Without tagging.

Haven't we discussed that?  Putting metadata off to the side introduces a bookkeeping problem.  It is a bad idea.

Yes, but I still have a lot of doubts about feedback with pragmas (I hope you view them as constructive criticism).

I'm finding this whole conversation exhausting.  


Me too :(
 
Is like pragmas assume there is always a perfect message transaction.
How can I halt the execution of a specific pragma?

By putting a break point in its implementations.

Can I write <myPragma halt>?

No.  But you can out a conditional breakpoint in CompiledMethod>>pragmaAt: or in the pragma's implementation.
How do I know if it will get executed?

By reading the broader system or adding break pints as just described.

Is <shortcut> a functional pragma?
How do I distinguis any pragma from being functional or "documentation"?

Using "implementors" and "senders" you can find out where it may be used.  One if the problems of late-bound systems is figuring out what binds to what.  Pragmas are more difficult to figure out unless pragmas have clearly commented implementations.


It could be broken because I pressed Alt+M in <gtInspectorAction> and nothing happens:

gtInspectorActionBrowse
    <gtInspectorAction>
    ^ GLMGenericAction new
        action: [ self browse ];
        icon: GLMUIThemeExtraIcons glamorousBrowse;
        title: 'Browse'
 
 
 
And they don't need to be in the method pane itself.

For some kinds of metadata, for metadata with semantics, not just a documentary function, it is important for the metadata to be obvious. 

I think this depends on context. Because your work could be towards low-level machinery details or software reenginering, doesn't mean that we all need to view compiler directives, functional and structural annotations, etc.

That's a mischaracterisation.  Most of their uses are for pluggable GUIs.  And if this is so onerous why weren't you protesting <primitive: 123>?


Pluggable GUIs in systems without GUI builders.

But yes, the same applies to the <primitive: 123> artifact. If we would have a Primitives Browser, what would be the point of accessing them through the normal browser?
 

And if I can write some prediction... When someone invents automatic annotation (like happens now with genomes) and decides it will be cool to have them in the image (because you will gain performance, more reflective capabilitites, etc) methods could explode with pragmas to the point gets to be annoying to browse any method. Then the tool will have to be built by need.
 
No one has argued for hiding the primitive specification off-to-the-side.  "Need" is a poor criticism here because using turing equivalence lots of things don't "need" to be the way they are.  Instead why not ask what are the pros and cons?


Ok, many of us knows the pros. I have been using pragmas for a while.
But if we stop discussing then it will never adapt to new ideas.
So you may want to share your view of cons too :)

The cons are that for years, and at length, one has to defend a good idea ;-).  


Ok, I am starting to think pragmas with tags are the best thing possibly ever created and the final word of evolution in this area ;)

Seriously, I am not saying is a bad idea at all. I say they could be visualized in other ways.
I cannot believe people accept happily that < ... > is the best way of representing annotations.

 
Pragmas were a new idea and here in thus conversation we see how resistant we are to new ideas.  I've seen nothing against the need for per-method metadata and a lot on how it can be done with other mechanisms.  But the existing mechanisms don't do one of two things
- separate normal from meta levels
- obviously associate metadata with methods.


I don't have the final answer but I suspect that because we used to see Smalltlak meta-levels through tools, we also "demand" that new meta-objects should cope well with our toolset.

 
So what I'm missing in this conversation is addressing the issues:
- how in a componentised loadable system do we decouple component loads where components collide in areas like global menu definitions, inspectors, etc?
- how do we associate metadata with methods so that 
   - the metadata is of a form that fits well with the host system?
   - the metadata is clearly associated with the method it is data of?
   - the bookkeeping is managed?

You could add good questions here.  But these are the questions I was thinking of when we added pragmas to VW.



I have more questions about having a controlled vocabulary for metadata and annotations, and how we could visualize them better. How could we add meta-annotations and if descriptive declarative programming could be avoided with sequential OO.
Naturally they could fit as bad questions for anyone.

Cheers,

Hernán
 
It is like having to specify protocol because there is no list pane to create them.

I disagree.  When the pragma is specifying type information, specifying that the method is an action on a specific menu, is a pane in an inspector, and many other uses, it is essential that that information be represented, and putting it in a one-off bookkeeping system is a bad idea.  We're not talking about simple documentary metadata like author, category etc. 

Well, I think documentary metadata is tremendously complex.
 
We're using pragmas for semantics, semantics of the method that are outside of its execution semantics, semantics about how the method fits in the broader system.  And putting that in non-obvious places is a bad idea.  


I agree. But obvious could be a place where can be located by a method though not necessarily visible.

Cheers,

Hernán

 


Hernán
 
About python decorators I disagree that are similar to pragmas. Pragmas are focused on being descriptive , python decorators are descriptive as by product. The main focus of python decorators is to shorten code by introducing syntactic sugar. 

Kilon, pragmas are not limited to being descriptive.
 

I agree though this is a very interesting discussion and I dont understand most of the things stated here so I leave an open door and mind for pragmas. Maybe one day I will "get it". 

That would be nice :) 



 

On Sat, Feb 7, 2015 at 10:02 AM, Thierry Goubier <[hidden email]> wrote:


2015-02-06 22:00 GMT+01:00 stepharo <[hidden email]>:
Really interesting discussion. I like pragmas but this is interesting to see them challenged.

Thanks. It's a pleasure to discuss that way :)
 
Yes, but there end up being lots of naming conventions and they are non-obvious.  Whereas pragmas, because they are in-your-face in the methods in question, don't need conventions. They just need documenting ;-).
Thierry I'm skeptical that multiple protocol will save the problem because you will rely on coding conventions.

Pragma as well: just explain the conventions behind the gtInspector pragmas, for example.

But give me multiple protocols and I'll show you the same conventions rewritten in less lines (and a slightly more efficient code).
 
And pragma is a clever tagging.

Then maybe we should remove protocols and replace them with pragmas :)

Thierry
 

Stef








--
best,
Eliot


Reply | Threaded
Open this post in threaded view
|

Re: ||

Eliot Miranda-2


On Sun, Feb 8, 2015 at 1:26 PM, Hernán Morales Durand <[hidden email]> wrote:
Hi Eliot,

2015-02-08 12:50 GMT-03:00 Eliot Miranda <[hidden email]>:
Hi Hernan,


On Feb 7, 2015, at 12:55 PM, Hernán Morales Durand <[hidden email]> wrote:

Hi Eliot,

2015-02-07 14:48 GMT-03:00 Eliot Miranda <[hidden email]>:
Hi Hernan,

On Sat, Feb 7, 2015 at 7:41 AM, Hernán Morales Durand <[hidden email]> wrote:

2015-02-07 5:59 GMT-03:00 kilon alios <[hidden email]>:
Personally I don't like Pragmas, they have not convinced me so far that they fit the style of Smalltalk syntax. I have to confess though I never liked descriptive elements and languages . 


Me neither. Actually the pragma idea is not wrong per se, it is the tag syntax to write them which bothers me. Because the world can be described with tags if you start that path.

How exactly is the syntax wrong?

I am not saying syntax is wrong, I just don't like it because:

1) Adds another level of representation inside an already reflective system.

What do you mean exactly?  I don't have clear recollection of whether they were in Squeak in 08 or if I ported then, but at that time CompiledMethod had a properties object, and pragmas were merged into this.  What I did do was save a lot of space getting rid if the properties object unless a method needed it.  And IIRC I changed the implementing class from MethodProperties to AdditionalMethodState.  So there was no additional level of representation.  a) the syntax was already there fir primitives and b) the state was already there in methods.


The place where pragmas are located internally are not an issue for me. The fact that special tags are not following the message pattern template is. It says there is a special collector, parser, validator, etc. a whole mechanism because something is - supposedly - not easily expressible with plain reflective messages.

I don't understand.  Pragmas are literal message patterns, period.  There is an exception for the primitive pragma so that the variable name for a primitive's error code can be introduced, but that's part of primitive parsing, not general pragma parsing.  At least in Squeak here's the code:

Parser>>pragmaSequence
"Parse a sequence of method pragmas."
[
(self matchToken: #<)
ifFalse: [ ^ self ].
self pragmaStatement.
(self matchToken: #>)
ifFalse: [ ^ self expected: '>' ] ] repeat

pragmaStatement
"Read a single pragma statement. Parse all generic pragmas in the form of: <key1: val1 key2: val2 ...> and remember them, including primitives."
| selector arguments words index keyword |
(hereType = #keyword or: [ hereType = #word or: [ hereType = #binary ] ])
ifFalse: [  ^ self expected: 'pragma declaration' ].

" This is a ugly hack into the compiler of the FFI package. FFI should be changed to use propre pragmas that can be parsed with the code here. "
(here = #apicall: or: [ here = #cdecl: ])
ifTrue: [ ^ self externalFunctionDeclaration ].

selector := String new.
arguments := OrderedCollection new.
words := OrderedCollection new.
[ hereType = #keyword or: [ (hereType = #word or: [ hereType = #binary ]) and: [ selector isEmpty ] ] ] whileTrue: [
index := self startOfNextToken + requestorOffset.
selector := selector , self advance.
words add: (index to: self endOfLastToken + requestorOffset).
(selector last = $: or: [ selector first isLetter not ])
ifTrue: [ arguments add: (self pragmaLiteral: selector) ] ].
selector numArgs ~= arguments size
ifTrue: [ ^ self expected: 'pragma argument' ].
(Symbol hasInterned: selector 
ifTrue: [ :value | keyword := value]) 
ifFalse: [ 
keyword := self 
correctSelector: selector wordIntervals: words
exprInterval: (words first first to: words last last)
ifAbort: [ ^ self fail ] ].
self addPragma: (Pragma keyword: keyword arguments: arguments asArray).
^ true
 
I can't speak for how its been implemented in Opal but I'd be surprised if it is using separate machinery.  The Squeak code above is different from the normal message parsing precisely so that it can insist that arguments are only literals (pragmaLiteral: above).


2) It could be done with plain common message sends.

No it can't. Common sends are executable and we don't want pragmas executed when the method is run, we want the pragma executed when the method is added, or analysed. That was what was ugly about the use of plain sends in e.f. VMMaker, that there had to be lots of empty implementations of the messages used for metadata.  

So using normal sends
- prevents the metadata from being directly executed because executing them when the method is run is wrong 
- confuses meta level and normal level, putting them at the same level, and hence...
- confusing for the programmer because its not obvious what's metadata and what's a normal send
- makes analysis harder for the same reason


We are talking about different worlds here.

So let;s stop talking because I;m getting frustrated.  I make a valid point about the inability to use normal selectors and you ignore my point.
 
Theoretically I could mark methods this way:

(Pragma
    for: (ASTBlockClosure >> #value:)
    selector: #primitive:
    arguments: (Array with: 60)) addPragma. 

So the annotations could be written with normal message sends.
And they could be tool supported, so no one gets confused.

So this is embedded in a method?  So it gets evaluated every time the method is executed?  Surely you're not serious.
 
 
3) Should be (to me) "hidden" from method pane, and displayed by a specific tool inside the system browser.

I disagree.  I want to see the pragma.  It has essential information that shouldn't be hidden.  I want to edit it easily.  

I want to see and edit the pragma too, when I am really interested. Just like with the bytecodes.
 
And how can you in the one hand say it can be implemented as a normal message send a d at the same time want it hidden?  Be consistent :-)


There is no inconsistency. I am saying they should be hidden from the method body.

The method pane you see in the browser should be used to send messages to your modeling domain (which already imposes its own difficulty), not being exploited to add meta information where meta could belong to instrumentation analysis (lint, profiling) or UI building (keymap, menu) or whatever excuse found to add more tags.

I wonder how one could refactor this method:

Greetings>>helloWorld
    <year: 2015>
    <status: #toDo>
    <author: 'Hernán'>
    <scope: #private>

    <soapOperationName: #HelloWorld>
    <soapDocumentation: #'Returns Hello World'>
    <soapResult: #String>
    <soapStyle: #RPC>

    <rmiOperationName: #HelloWorld>
    <rmiDocumentation: #'Returns Hello World'>
    <rmiResult: #String>
   
    <asn1OperationName: #HelloWorld>
    <asn1Documentation: #'Returns Hello World'>
    <asn1Result: #UTF8String>
   
    <dcomOperationName: #HelloWorld>
    <dcomDocumentation: #'Returns Hello World'>
    <dcomResult: #String>
   
    ^'Hello World'

Thus:

first, date & author can be recovered from the method source via timestamp, but if you want to separate the author of the text from the last editor of the method then...
 
 Greetings>>helloWorld
    <addDocPage: #Greetings year: 2015 status: #toDo author: 'Hernán' scope: #private>
    <soapOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String style: #RPC>
    <rmiOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String>
    <asn1OperationOperation: #HelloWorld documentation: #'Returns Hello World' resultType:#UTF8String>
    <dcomOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String>
    
    ^'Hello World'

and then have implementations of e.g. SoapInterfaceBuilder>>soapOperation:documentation:returnType:style:, ASN1InterfaceBuilder>> asn1Operation:documentation:returnType:style:, etc, that add the method to the interface they're building.

So, assuming your interface methods are in a class hierarchy from SomeSoapInterfaceSubclass up to SomeSoapInterfaceBaseClass building looks like, e.g.:

    | builder |
    builder := SoapInterfaceBuilder new.
    (Pragma
            allNamed: #soapOperation:documentation:returnType:style:
            from: SomeSoapInterfaceSubclass
            to: SomeSoapInterfaceBaseClass) do:
        [:pragma|
        builder method: pragma method.
        pragma message sendTo: builder]

But if you're able you'll do it just like this:

Greetings>>helloWorld
    <addDocPage: #Greetings year: 2015 status: #toDo author: 'Hernán' scope: #private>
    <externalOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #UTF8String style: #RPC>
    
    ^'Hello World'

implement the same method in the various builders, and coerce UTF8String to String in those that only handle simple notions of string type.

Why on _earth_ are people writing 17 pragmas where I see only two?

Until we have discussed this I'm not going to waste effort responding to the points below.  I think we're talking past each other.  I don't see your Greetings example displaying any understanding of what pragma syntax is, or how pragmas can, or should be used.  So let's look at the above.  Perhaps we can both be less exhausted.



The <literalMessagePattern> syntax predates pragmas.  It was used first for numeric primitives in Smalltalk-76 or Smalltalk-80.  Squeak extended it with primitive:module:.  I and others extended it to include arbitrary literal message patterns.  The syntax of a literal message pattern is the syntax of a send with no receiver and only literal arguments. 
The use of this syntax means
a) no new syntax
b) each pragma is potentially executable
c) methods using specific pragmas can be found using "find senders"
d) the execution side of a pragma can be found using "find implementors"

So what's wrong with that?  How is it wrong to use a common Smalltalk object, a Message, that is well-supported in the system, for method metadata?


I get that pragmas are messages, but they assume an implicit receiver, which actually depends on context. If I understood right with pragmas always receiver = destination?

Not for pragmas that are just labels.  And what's destination?  In the menu building example above the destination"is the menu but the receiver is the menu builder.  So I think that what the receiver is depends on usage.

  If you change things in the communication model (receiver, sender, message, etc.), by removing or adding elements, you have a loss in the message because it gets harder to reconstruct the message send.

I don't understand this.  Can you expand?


Now I realize how far we are from understanding. But I start to feel tired to write about communication models here.
 

Consider

<eventRegistration>
| eventRegistration |
{ eventRegistration }.
self eventRegistration.

which of them "it sounds like" you cannot infer their purpose?

I don't get the example, because of the confusion of meta layers.


Now you understand me :)
 
<eventRegistration>
says "this is metadata"


yes, but not what type of metadata is. Is metadata for instrumentation? is for documentation?
 
| eventRegistration |

says "this is a bug in the method because the variable isn't used, and eg Opal will remove it so it won't be there".


but you get this is a local variable supposed to be used in the current method. You can get the scope easily.

 
{ eventRegistration }.
I guess you mean { #eventRegistration }.  If so this is the same.  An optimizing compiler will delete it.


Yes. The idea there is the same, you would associate the eventRegistration as an Array element to be accessed in the current method for example.
 
self eventRegistration.
says "send myself eventRegustration".  Which /isn't/ what's wanted.

So for me only the pragma implies "this method is to be registered with the event system".  The middle two say "I am a bug, or syntax error".  The last one says "I am a normal send".


To me says "this method contains code which defines an event". Where the event is defined should need more metadata until explicit semantics are enough complete. 


To me the first because you need the context MyClass>>methodName
and you need to browse the pragma to get its purpose.


 
There are other ways to add metadata to methods. Without tagging.

Haven't we discussed that?  Putting metadata off to the side introduces a bookkeeping problem.  It is a bad idea.

Yes, but I still have a lot of doubts about feedback with pragmas (I hope you view them as constructive criticism).

I'm finding this whole conversation exhausting.  


Me too :(
 
Is like pragmas assume there is always a perfect message transaction.
How can I halt the execution of a specific pragma?

By putting a break point in its implementations.

Can I write <myPragma halt>?

No.  But you can out a conditional breakpoint in CompiledMethod>>pragmaAt: or in the pragma's implementation.
How do I know if it will get executed?

By reading the broader system or adding break pints as just described.

Is <shortcut> a functional pragma?
How do I distinguis any pragma from being functional or "documentation"?

Using "implementors" and "senders" you can find out where it may be used.  One if the problems of late-bound systems is figuring out what binds to what.  Pragmas are more difficult to figure out unless pragmas have clearly commented implementations.


It could be broken because I pressed Alt+M in <gtInspectorAction> and nothing happens:

gtInspectorActionBrowse
    <gtInspectorAction>
    ^ GLMGenericAction new
        action: [ self browse ];
        icon: GLMUIThemeExtraIcons glamorousBrowse;
        title: 'Browse'
 
 
 
And they don't need to be in the method pane itself.

For some kinds of metadata, for metadata with semantics, not just a documentary function, it is important for the metadata to be obvious. 

I think this depends on context. Because your work could be towards low-level machinery details or software reenginering, doesn't mean that we all need to view compiler directives, functional and structural annotations, etc.

That's a mischaracterisation.  Most of their uses are for pluggable GUIs.  And if this is so onerous why weren't you protesting <primitive: 123>?


Pluggable GUIs in systems without GUI builders.

But yes, the same applies to the <primitive: 123> artifact. If we would have a Primitives Browser, what would be the point of accessing them through the normal browser?
 

And if I can write some prediction... When someone invents automatic annotation (like happens now with genomes) and decides it will be cool to have them in the image (because you will gain performance, more reflective capabilitites, etc) methods could explode with pragmas to the point gets to be annoying to browse any method. Then the tool will have to be built by need.
 
No one has argued for hiding the primitive specification off-to-the-side.  "Need" is a poor criticism here because using turing equivalence lots of things don't "need" to be the way they are.  Instead why not ask what are the pros and cons?


Ok, many of us knows the pros. I have been using pragmas for a while.
But if we stop discussing then it will never adapt to new ideas.
So you may want to share your view of cons too :)

The cons are that for years, and at length, one has to defend a good idea ;-).  


Ok, I am starting to think pragmas with tags are the best thing possibly ever created and the final word of evolution in this area ;)

Seriously, I am not saying is a bad idea at all. I say they could be visualized in other ways.
I cannot believe people accept happily that < ... > is the best way of representing annotations.

 
Pragmas were a new idea and here in thus conversation we see how resistant we are to new ideas.  I've seen nothing against the need for per-method metadata and a lot on how it can be done with other mechanisms.  But the existing mechanisms don't do one of two things
- separate normal from meta levels
- obviously associate metadata with methods.


I don't have the final answer but I suspect that because we used to see Smalltlak meta-levels through tools, we also "demand" that new meta-objects should cope well with our toolset.

 
So what I'm missing in this conversation is addressing the issues:
- how in a componentised loadable system do we decouple component loads where components collide in areas like global menu definitions, inspectors, etc?
- how do we associate metadata with methods so that 
   - the metadata is of a form that fits well with the host system?
   - the metadata is clearly associated with the method it is data of?
   - the bookkeeping is managed?

You could add good questions here.  But these are the questions I was thinking of when we added pragmas to VW.



I have more questions about having a controlled vocabulary for metadata and annotations, and how we could visualize them better. How could we add meta-annotations and if descriptive declarative programming could be avoided with sequential OO.
Naturally they could fit as bad questions for anyone.

Cheers,

Hernán
 
It is like having to specify protocol because there is no list pane to create them.

I disagree.  When the pragma is specifying type information, specifying that the method is an action on a specific menu, is a pane in an inspector, and many other uses, it is essential that that information be represented, and putting it in a one-off bookkeeping system is a bad idea.  We're not talking about simple documentary metadata like author, category etc. 

Well, I think documentary metadata is tremendously complex.
 
We're using pragmas for semantics, semantics of the method that are outside of its execution semantics, semantics about how the method fits in the broader system.  And putting that in non-obvious places is a bad idea.  


I agree. But obvious could be a place where can be located by a method though not necessarily visible.

Cheers,

Hernán

 


Hernán
 
About python decorators I disagree that are similar to pragmas. Pragmas are focused on being descriptive , python decorators are descriptive as by product. The main focus of python decorators is to shorten code by introducing syntactic sugar. 

Kilon, pragmas are not limited to being descriptive.
 

I agree though this is a very interesting discussion and I dont understand most of the things stated here so I leave an open door and mind for pragmas. Maybe one day I will "get it". 

That would be nice :) 



 

On Sat, Feb 7, 2015 at 10:02 AM, Thierry Goubier <[hidden email]> wrote:


2015-02-06 22:00 GMT+01:00 stepharo <[hidden email]>:
Really interesting discussion. I like pragmas but this is interesting to see them challenged.

Thanks. It's a pleasure to discuss that way :)
 
Yes, but there end up being lots of naming conventions and they are non-obvious.  Whereas pragmas, because they are in-your-face in the methods in question, don't need conventions. They just need documenting ;-).
Thierry I'm skeptical that multiple protocol will save the problem because you will rely on coding conventions.

Pragma as well: just explain the conventions behind the gtInspector pragmas, for example.

But give me multiple protocols and I'll show you the same conventions rewritten in less lines (and a slightly more efficient code).
 
And pragma is a clever tagging.

Then maybe we should remove protocols and replace them with pragmas :)

Thierry
 

Stef








--
best,
Eliot





--
best,
Eliot
Reply | Threaded
Open this post in threaded view
|

Re: ||

Nicolai Hess
In reply to this post by hernanmd


2015-02-08 22:26 GMT+01:00 Hernán Morales Durand <[hidden email]>:

It could be broken because I pressed Alt+M in <gtInspectorAction> and nothing happens:

gtInspectorActionBrowse
    <gtInspectorAction>
    ^ GLMGenericAction new
        action: [ self browse ];
        icon: GLMUIThemeExtraIcons glamorousBrowse;
        title: 'Browse'

selecting the word gtInspectorAction and pressing Alt+n works, it
opens the "Senders or Users" MessageBrowser.
 


Reply | Threaded
Open this post in threaded view
|

Re: ||

hernanmd
In reply to this post by Eliot Miranda-2


2015-02-08 19:46 GMT-03:00 Eliot Miranda <[hidden email]>:


On Sun, Feb 8, 2015 at 1:26 PM, Hernán Morales Durand <[hidden email]> wrote:
Hi Eliot,

2015-02-08 12:50 GMT-03:00 Eliot Miranda <[hidden email]>:
Hi Hernan,


On Feb 7, 2015, at 12:55 PM, Hernán Morales Durand <[hidden email]> wrote:

Hi Eliot,

2015-02-07 14:48 GMT-03:00 Eliot Miranda <[hidden email]>:
Hi Hernan,

On Sat, Feb 7, 2015 at 7:41 AM, Hernán Morales Durand <[hidden email]> wrote:

2015-02-07 5:59 GMT-03:00 kilon alios <[hidden email]>:
Personally I don't like Pragmas, they have not convinced me so far that they fit the style of Smalltalk syntax. I have to confess though I never liked descriptive elements and languages . 


Me neither. Actually the pragma idea is not wrong per se, it is the tag syntax to write them which bothers me. Because the world can be described with tags if you start that path.

How exactly is the syntax wrong?

I am not saying syntax is wrong, I just don't like it because:

1) Adds another level of representation inside an already reflective system.

What do you mean exactly?  I don't have clear recollection of whether they were in Squeak in 08 or if I ported then, but at that time CompiledMethod had a properties object, and pragmas were merged into this.  What I did do was save a lot of space getting rid if the properties object unless a method needed it.  And IIRC I changed the implementing class from MethodProperties to AdditionalMethodState.  So there was no additional level of representation.  a) the syntax was already there fir primitives and b) the state was already there in methods.


The place where pragmas are located internally are not an issue for me. The fact that special tags are not following the message pattern template is. It says there is a special collector, parser, validator, etc. a whole mechanism because something is - supposedly - not easily expressible with plain reflective messages.

I don't understand.  Pragmas are literal message patterns, period.  There is an exception for the primitive pragma so that the variable name for a primitive's error code can be introduced, but that's part of primitive parsing, not general pragma parsing.  At least in Squeak here's the code:

Parser>>pragmaSequence
"Parse a sequence of method pragmas."
[
(self matchToken: #<)
ifFalse: [ ^ self ].
self pragmaStatement.
(self matchToken: #>)
ifFalse: [ ^ self expected: '>' ] ] repeat

pragmaStatement
"Read a single pragma statement. Parse all generic pragmas in the form of: <key1: val1 key2: val2 ...> and remember them, including primitives."
| selector arguments words index keyword |
(hereType = #keyword or: [ hereType = #word or: [ hereType = #binary ] ])
ifFalse: [  ^ self expected: 'pragma declaration' ].

" This is a ugly hack into the compiler of the FFI package. FFI should be changed to use propre pragmas that can be parsed with the code here. "
(here = #apicall: or: [ here = #cdecl: ])
ifTrue: [ ^ self externalFunctionDeclaration ].

selector := String new.
arguments := OrderedCollection new.
words := OrderedCollection new.
[ hereType = #keyword or: [ (hereType = #word or: [ hereType = #binary ]) and: [ selector isEmpty ] ] ] whileTrue: [
index := self startOfNextToken + requestorOffset.
selector := selector , self advance.
words add: (index to: self endOfLastToken + requestorOffset).
(selector last = $: or: [ selector first isLetter not ])
ifTrue: [ arguments add: (self pragmaLiteral: selector) ] ].
selector numArgs ~= arguments size
ifTrue: [ ^ self expected: 'pragma argument' ].
(Symbol hasInterned: selector 
ifTrue: [ :value | keyword := value]) 
ifFalse: [ 
keyword := self 
correctSelector: selector wordIntervals: words
exprInterval: (words first first to: words last last)
ifAbort: [ ^ self fail ] ].
self addPragma: (Pragma keyword: keyword arguments: arguments asArray).
^ true
 
I can't speak for how its been implemented in Opal but I'd be surprised if it is using separate machinery.  The Squeak code above is different from the normal message parsing precisely so that it can insist that arguments are only literals (pragmaLiteral: above).


Ok, I will stop here because I see contradictions and no way we can agree on them.
Amazing code BTW.

 

2) It could be done with plain common message sends.

No it can't. Common sends are executable and we don't want pragmas executed when the method is run, we want the pragma executed when the method is added, or analysed. That was what was ugly about the use of plain sends in e.f. VMMaker, that there had to be lots of empty implementations of the messages used for metadata.  

So using normal sends
- prevents the metadata from being directly executed because executing them when the method is run is wrong 
- confuses meta level and normal level, putting them at the same level, and hence...
- confusing for the programmer because its not obvious what's metadata and what's a normal send
- makes analysis harder for the same reason


We are talking about different worlds here.

So let;s stop talking because I;m getting frustrated.  I make a valid point about the inability to use normal selectors and you ignore my point.
 
Theoretically I could mark methods this way:

(Pragma
    for: (ASTBlockClosure >> #value:)
    selector: #primitive:
    arguments: (Array with: 60)) addPragma. 

So the annotations could be written with normal message sends.
And they could be tool supported, so no one gets confused.

So this is embedded in a method?  So it gets evaluated every time the method is executed?  Surely you're not serious.
 

Precisely that is what should happens behind the curtains. I cannot believe why is so hard to understand.

 
 
3) Should be (to me) "hidden" from method pane, and displayed by a specific tool inside the system browser.

I disagree.  I want to see the pragma.  It has essential information that shouldn't be hidden.  I want to edit it easily.  

I want to see and edit the pragma too, when I am really interested. Just like with the bytecodes.
 
And how can you in the one hand say it can be implemented as a normal message send a d at the same time want it hidden?  Be consistent :-)


There is no inconsistency. I am saying they should be hidden from the method body.

The method pane you see in the browser should be used to send messages to your modeling domain (which already imposes its own difficulty), not being exploited to add meta information where meta could belong to instrumentation analysis (lint, profiling) or UI building (keymap, menu) or whatever excuse found to add more tags.

I wonder how one could refactor this method:

Greetings>>helloWorld
    <year: 2015>
    <status: #toDo>
    <author: 'Hernán'>
    <scope: #private>

    <soapOperationName: #HelloWorld>
    <soapDocumentation: #'Returns Hello World'>
    <soapResult: #String>
    <soapStyle: #RPC>

    <rmiOperationName: #HelloWorld>
    <rmiDocumentation: #'Returns Hello World'>
    <rmiResult: #String>
   
    <asn1OperationName: #HelloWorld>
    <asn1Documentation: #'Returns Hello World'>
    <asn1Result: #UTF8String>
   
    <dcomOperationName: #HelloWorld>
    <dcomDocumentation: #'Returns Hello World'>
    <dcomResult: #String>
   
    ^'Hello World'

Thus:

first, date & author can be recovered from the method source via timestamp, but if you want to separate the author of the text from the last editor of the method then...
 
 Greetings>>helloWorld
    <addDocPage: #Greetings year: 2015 status: #toDo author: 'Hernán' scope: #private>
    <soapOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String style: #RPC>
    <rmiOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String>
    <asn1OperationOperation: #HelloWorld documentation: #'Returns Hello World' resultType:#UTF8String>
    <dcomOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String>
    
    ^'Hello World'

and then have implementations of e.g. SoapInterfaceBuilder>>soapOperation:documentation:returnType:style:, ASN1InterfaceBuilder>> asn1Operation:documentation:returnType:style:, etc, that add the method to the interface they're building.

So, assuming your interface methods are in a class hierarchy from SomeSoapInterfaceSubclass up to SomeSoapInterfaceBaseClass building looks like, e.g.:

    | builder |
    builder := SoapInterfaceBuilder new.
    (Pragma
            allNamed: #soapOperation:documentation:returnType:style:
            from: SomeSoapInterfaceSubclass
            to: SomeSoapInterfaceBaseClass) do:
        [:pragma|
        builder method: pragma method.
        pragma message sendTo: builder]

But if you're able you'll do it just like this:

Greetings>>helloWorld
    <addDocPage: #Greetings year: 2015 status: #toDo author: 'Hernán' scope: #private>
    <externalOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #UTF8String style: #RPC>
    
    ^'Hello World'

implement the same method in the various builders, and coerce UTF8String to String in those that only handle simple notions of string type.

Why on _earth_ are people writing 17 pragmas where I see only two?


Not the point I wanted to address, but thanks for the example and answering the questions patiently
 
Cheers,

Hernán

Reply | Threaded
Open this post in threaded view
|

Re: ||

Frank Shearar-3
In reply to this post by Eliot Miranda-2
On 6 February 2015 at 17:38, Eliot Miranda <[hidden email]> wrote:

> Hi Frank,
>
> On Fri, Feb 6, 2015 at 2:29 AM, Frank Shearar <[hidden email]>
> wrote:
>>
>> On 5 February 2015 at 21:20, Thierry Goubier <[hidden email]>
>> wrote:
>> >
>> >
>> > 2015-02-05 21:28 GMT+01:00 Eliot Miranda <[hidden email]>:
>> >>
>> >>
>> >>
>> >> On Thu, Feb 5, 2015 at 11:34 AM, Thierry Goubier
>> >> <[hidden email]> wrote:
>> >>>
>> >>>
>> >>>
>> >>> 2015-02-05 18:51 GMT+01:00 Eliot Miranda <[hidden email]>:
>> >>>>
>> >>>>
>> >>>>
>> >>>> On Thu, Feb 5, 2015 at 2:31 AM, Thierry Goubier
>> >>>> <[hidden email]> wrote:
>> >>>>>
>> >>>>>
>> >>>>>
>> >>>>> 2015-02-05 10:55 GMT+01:00 Sven Van Caekenberghe <[hidden email]>:
>> >>>>>>
>> >>>>>> It is obviously a compromise (or a continuum) between abstractions
>> >>>>>> and
>> >>>>>> performance.
>> >>>>>
>> >>>>>
>> >>>>> I agree. With a special view in that we are in a sub domain where
>> >>>>> simple things well designed (Smalltalk, that is) are amazingly good
>> >>>>> at
>> >>>>> supporting complex designs.
>> >>>>>
>> >>>>>>
>> >>>>>>
>> >>>>>> But there should remain a focus on efficiency (not just speed but
>> >>>>>> also
>> >>>>>> memory), it is hard to fix these things years later.
>> >>>>>
>> >>>>>
>> >>>>> And I like the fact that efficient code and design is often a
>> >>>>> pleasure
>> >>>>> to read and learn from :)
>> >>>>>
>> >>>>> Now, being radical: could we get rid of pragmas ? The only reason I
>> >>>>> see
>> >>>>> to them is that they allow extension by external packages, because
>> >>>>> we can't
>> >>>>> have methods which belong to two protocols (*).
>> >>>>
>> >>>>
>> >>>> They are a Smalltalk-centric way of adding arbitrary metadata to
>> >>>> methods; Smalltalk-centric in that a pragma is a Message instance,
>> >>>> may be
>> >>>> queried for senders, performed, etc, and that it can be parsed using
>> >>>> the
>> >>>> standard compiler (they add no new syntax).  They have been broadly
>> >>>> used.
>> >>>> IME they have simplified and reduced code where ever they have been
>> >>>> used.
>> >>>> They don't have to be there but they're a good thing.  Why do you
>> >>>> want to
>> >>>> get rid of them?
>> >>>
>> >>>
>> >>> Because the "they have simplified and reduced code where ever they
>> >>> have
>> >>> been used" is wrong. I just have to give you a counter example:
>> >>
>> >>
>> >> OK, the claim is too strong.  But they /have/ simplified code in cases
>> >> where they're appropriate.  And I can cite several examples.
>> >>
>> >>>
>> >>>
>> >>> One of the uses of pragmas is associating methods containing Gui
>> >>> commands
>> >>> or settings to specific objects. Based on an object inspected or
>> >>> selected,
>> >>> you search among all its methods the ones containing a specific pragma
>> >>> (and
>> >>> you order them by a parameter to that pragma, if you want), and you
>> >>> execute
>> >>> that method to retrieve the objects you want (presentations, menu
>> >>> commands,
>> >>> shortcuts, you name it, I use it :)).
>> >>>
>> >>> The code to do that is exactly as long as the one which, on the same
>> >>> object, retrieve all methods under a certain protocol (the latter
>> >>> being
>> >>> faster than the pragma one, to boot).
>> >>>
>> >>> Each method is one line longer ("the pragma").
>> >>>
>> >>> Each such method usually has in its name a copy of the pragma
>> >>> (gtInspectorXXX methods, I'm looking at you), because of course this
>> >>> is far
>> >>> more user friendly to indicate its purpose in the method name than in
>> >>> only
>> >>> the pragma.
>> >>>
>> >>> (There are two more arguments for the use of pragmas in that context,
>> >>> one
>> >>> which has a direct counter-example, one which hasn't: )
>> >>>
>> >>> Moreover, the semantic of pragmas is "interesting" to describe, and in
>> >>> some cases, require a good amount of dark magic about a global object
>> >>> listening to all methods changes and capturing (and executing) certain
>> >>> methods in a vague relation about when this is going to happen, or
>> >>> being
>> >>> triggered on specific system events (main menu rebuilding, anyone?).
>> >>> The
>> >>> funny thing is to see that pattern visible on a profile when loading
>> >>> packages (talk of a scalable approach).
>> >>
>> >>
>> >> But triggering in the background happens for maintaining change sets,
>> >> notifying other clients too.  It's not as if pragmas introduced such
>> >> triggering; that kind of triggering has been in use for a long time.
>> >> And
>> >> being able to reshape the GUI automatically is very useful.
>> >
>> >
>> > I don't contest the possibilities, it's just that they add a significant
>> > layer of complexity when non mastered (how many Pharo developpers know
>> > which
>> > event you have to register to to receive all new methods notifications?
>> > Is
>> > that documented in one of the books?), and that, except for using them
>> > as
>> > <primitives> or for extensibility, I see other syntaxes and smalltalk
>> > code
>> > which are simpler.
>> >
>> > A good example is that the pragma syntax is never included in the one
>> > page
>> > Smalltalk syntax description :)
>> >
>> >>
>> >>
>> >>>
>> >>>
>> >>>>
>> >>>> (and yes, I'm biassed)
>> >>>
>> >>>
>> >>> Then you're the right person to give me counter arguments...
>> >>>
>> >>> (Now, I'd look differently at pragmas used for gradual typing and so
>> >>> on... But even for something like FFI, I'd seriously prefer to have
>> >>> Smalltalk calls to describe the call and its arguments than a kind of
>> >>> script
>> >>> hidden inside pragmas, just for the discoverability and because it
>> >>> makes one
>> >>> less idiom to deal with)
>> >>
>> >>
>> >> Why?  A good use of pragmas is to associate meta data with a particular
>> >> method.  Having calls off to the side always introduces the need for
>> >> book-keeping to keep those methods off to the side in sync with the
>> >> methods
>> >> they're describing.  Typically everyone rolls their own.  But here
>> >> we're
>> >> adding a level of triggering just to keep the metadata methods in sync.
>> >
>> >
>> > I agree with the "metadata", but I'd prefer a executable, evaluate that
>> > block as a medata literal than the pragma. Something that says
>> > "onceAndStoreAsMetadata", to a block, for example. An API to compiled
>> > methods which says add metadata.
>> >
>> > I strongly agree with your keep it in sync argument, still. Pragmas are
>> > better than nothing.
>> >
>> >>
>> >>
>> >> There is no such need with pragmas; they are always in sync with the
>> >> methods they describe because they are embedded in their methods.
>> >> Instead
>> >> we can use triggering to do useful things, adding a pane to open
>> >> inspectors
>> >> as soon as we define the method that describes the pane, adding or
>> >> removing
>> >> a menu entry, etc.
>> >
>> >
>> > Just a naming convention does just that perfectly fine, and with less
>> > lines
>> > (except for extensions by external packages) and faster code in many
>> > cases.
>> >
>> >>
>> >>
>> >> This is one idiom that covers a host of other cases.  That's why I
>> >> claim
>> >> that whenever I've seen it used it has reduced complexity.
>> >>
>> >> Some history.  Steve Dahl, I developed pragmas at ParcPlace, with
>> >> Vassili
>> >> Bykov adding abstractions for accessing them.  The first step was to
>> >> replace
>> >> some ugly class-side code to set unwind bits in ensure: and
>> >> ifCurtailed: by
>> >> a pragma the compiler would recognise and set the bits itself.  The
>> >> first
>> >> real use was to make the VisualWorks launcher's menus extensible.
>> >> Before
>> >> pragmas the launcher's menu was static and had lots of disabled entries
>> >> for
>> >> launching tools that were sold separately such as DLLAndCConnect.  With
>> >> pragmas the launcher's menu was defined with the base system's tools
>> >> and
>> >> then extended as each tool package was loaded, or cut-back as each tool
>> >> was
>> >> unloaded.  So that decoupled the launcher from introducing new tools.
>> >> A
>> >> nice result.
>> >>
>> >> We then started using it for the browser and one could plug-in a single
>> >> tool without redefining the browser's menu methods, which decoupled
>> >> each
>> >> extension.  All this was done in the context of the parcel system,
>> >> where we
>> >> could rapidly load packages (parcels ~= Fuel).  Pragmas allowed us to
>> >> decouple these tools where they collided in places like menu
>> >> definition,
>> >> tool registration.
>> >>
>> >> Then Tami Lee, who was managing the COM connection that turned a VW
>> >> image
>> >> into a COM server, became the first "user" of pragmas outside of myself
>> >> and
>> >> Steve. She used it to replace a lot of class-side methods that defined
>> >> the
>> >> signatures of methods that comprised the server.  It was a lovely
>> >> clean-up.
>> >> One could define the COM signature for a method in the method itself,
>> >> and
>> >> the class side lost about three separate methods that defined all that
>> >> metadata.  One could read the server method itself and understand its
>> >> semantics without having to consult the class-side methods.  One didn't
>> >> have
>> >> to know that there was metadata hidden on the class side because it was
>> >> right there in your face.
>> >>
>> >> Then Vassili used it for his cool inspector framework, Trippy, which
>> >> was
>> >> similar to Glamour in some ways, and was a huge improvement over the
>> >> old
>> >> Inspector framework, again resulting in a much more pluggable,
>> >> decoupled and
>> >> extensible system.  Vassili also added the abstractions for accessing
>> >> pragmas in methods.
>> >>
>> >> Then we added checking so that one could restrict the compiler to
>> >> accept
>> >> only legal pragmas for a given class.  But if we defined the legal
>> >> pragmas
>> >> in a class-side method, say legalPragmas, then this would be exactly
>> >> the
>> >> kind of single point for extensions that causes collisions between
>> >> packages,
>> >> each of which might want to add its own set of pragmas.  The
>> >> solution... use
>> >> a pragma to mark a class-side method as defining a set of legal pragmas
>> >> for
>> >> a class.  One could have more than one method defining a set of legal
>> >> pragmas; packages wishing to add their own cool pragmas were decoupled.
>> >> Once the system because recursive, it had to be a good idea ;-).
>> >
>> >
>> > Ok, I start to see where the abstraction wasn't working so well... since
>> > pragmas are not executed, when writing a method you can't know if the
>> > pragma
>> > is correct, because even executing the method may not trigger the pragma
>> > induced code. So you need the legalPragmas to give metadata on metadata
>> > for
>> > the compiler to do a bit of static checking, but it doesn't work for
>> > system-wide pragmas unless you extend Object :(
>> >
>> > And often it doesn't matter if the pragma reference a completely non
>> > existent method or api, since it is probably never executed by anybody
>> > (and
>> > if it is, it won't probably reify the error message properly as a
>> > compilation error as it should, because it may be triggered miles away
>> > from
>> > the system browser).
>>
>> Pragmas don't execute. They're _data_. There is no "calls unknown
>> sender" because the don't execute.
>
>
> I think they can do both, which is nice.  I actually prefer uses of pragmas
> where they /are/ executable.  They ca be performed by some object, and that
> execution can modify the system in the desired way, for example having a
> menu builder perform the menu definition pragma in a menu action method to
> add that action to a menu.
>
>>
>> Eliot's point is that pragmas _describe_, and then other systems act
>> on those descriptions.
>
>
> Right.  But that description is executable by something else.  Unlike, for
> example, a block as metadata which is only executable.

Yep. I certainly see no contradiction between us: you're saying that
the description the pragma provides also provides all the data needed
for an object (which might be the class with the pragma'd method) to
do something meaningful. Sure, absolutely.

>> They're just like Java or C# attributes, or Python decorators. Only
>> they're better, because Java/C# attributes can do anything, whereas
>> pragmas merely describe.
>
>
> Are you sure Java and C# attributes are executable?  When I read the
> wikipedia page for Java attributes I get the notion that they're structured
> non-executable data, i.e.:
>
> "When Java source code is compiled, annotations can be processed by compiler
> plug-ins called annotation processors. Processors can produce informational
> messages or create additional Java source files or resources, which in turn
> may be compiled and processed, and also modify the annotated code itself.
> The Java compiler conditionally stores annotation metadata in the class
> files, if the annotation has aRetentionPolicy of CLASS or RUNTIME. Later,
> the JVM or other programs can look for the metadata to determine how to
> interact with the program elements or change their behavior.
>
> In addition to processing an annotation using an annotation processor, a
> Java programmer can write their own code that uses reflections to process
> the annotation. Java SE 5 supports a new interface that is defined in the
> java.lang.reflect package. This package contains the interface called
> AnnotatedElement that is implemented by the Java reflection classes
> including Class, Constructor, Field,Method, and Package. The implementations
> of this interface are used to represent an annotated element of the program
> currently running in the Java Virtual Machine. This interface allows
> annotations to be read reflectively."
>
> The microsoft doc on C# indicates that they're declarative, but no mention
> of those declarations being executable:
> "C# enables programmers to invent new kinds of declarative information,
> called attributes. Programmers can then attach attributes to various program
> entities, and retrieve attribute information in a run-time environment. For
> instance, a framework might define a HelpAttribute attribute that can be
> placed on certain program elements (such as classes and methods) to provide
> a mapping from those program elements to their documentation."

In C# the attributes are constructed when the assembly containing the
attribute-decorated class is loaded. Since they are just normal
objects, you may do anything you like in their constructor.

// In some random library you import
public class FriendlyAttribute: Attribute {
    public class FriendlyAttribute(string path) {
        System.IO.Directory.Delete(path)
    }
}

// In your own assembly MyAssembly
[Friendly("C:\\Users\\frank\\Documents")]
public class Foo {
}

When MyAssembly loads, that directory's gone (modulo file
permissions). There is no way of knowing what an attribute will do
without actually reading the source/

I am _pretty sure_ the same is true of Java, but I last used Java in
anger about 3 years ago, so I may be mistaken.

Now, I agree that the above example is contrived and ridiculous, but I
hope you see the point that C# attributes _look_ like just data, but
really aren't.

frank

>> frank
>>
>> >> There are other uses; you've seen them.  I used them in VMMaker to
>> >> eliminate metadata that was embedded as sends to methods defined as
>> >> ^self
>> >> that Slang had to extract and analyse, and filter-out from generated
>> >> code.
>> >> They simplified Slang's code anaylsis, made the simulator more
>> >> efficient
>> >> (since there were no longer sends to execute).  My point is that in all
>> >> the
>> >> cases I've seen, using pragmas has
>> >> - simplified the code
>> >> - made it obvious that methods have metadata associated with them
>> >> - replaced specialized ways of associating metadata with code by the
>> >> general pragma mechanism
>> >> and in many of the cases it has
>> >> - provided a more decoupled system
>> >> - provided a more dynamic and extensible system
>> >
>> >
>> > Yes, and I can point out some of its shortcomings: it's non-obvious,
>> > it's
>> > limited, tools, even that many years later don't support them well (in
>> > Squeak or Pharo, at least), its redundant in quite a few variants.
>> >
>> > Please, could we improve a bit? Methods belonging to multiple protocols
>> > would give us the same decoupling as pragmas, and I would be free to
>> > avoid
>> > them where I shouldn't have to use them :)
>> >
>> >>
>> >>
>> >> I've been meaning to write up the history of pragmas for ages, but
>> >> Vassili, Steve or I have always been too busy.  I think a community
>> >> paper on
>> >> their use and history would be worth-while, and might go a long way to
>> >> reduce antipathies like yours.  I will forever be in debt to anyone who
>> >> wants to volunteer to help me write such a paper.
>> >
>> >
>> > That would certainly be interesting :)
>> >
>> >>
>> >>
>> >>>
>> >>>
>> >>> Thierry
>> >>>
>> >>> (Look. I started using Smalltalk in 1992... and up to your
>> >>> description, I
>> >>> wasn't aware pragmas were supposed to follow message syntax ;) Thanks
>> >>> for
>> >>> the explanation, by the way)
>> >>
>> >>
>> >> They /have/ to follow literal message syntax.  t's all the compiler
>> >> will
>> >> accept.  That's why there needs to be a paper.
>> >
>> >
>> > Yes!
>> >
>> > Thanks for taking the time to argument,
>> >
>> > Thierry
>> >
>> >>
>> >>
>> >>
>> >> --
>> >> best,
>> >> Eliot
>>
>
>
>
> --
> best,
> Eliot

1234