Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
September 2017
- 546 messages
Re: [Pharo-dev] [Ann] Class meta annotations
by Denis Kudriashov
So I renamed it to ClassAnnotation with all related names.
But I keep meta prefix in #metaAnnotations Class extension to avoid general
name:
MyClass metaAnnotations
You can check updated readme for details
https://github.com/dionisiydk/ClassAnnotation
2017-09-26 17:31 GMT+02:00 Stephane Ducasse <stepharo.self(a)gmail.com>:
> ;)
>
> On Tue, Sep 26, 2017 at 1:28 PM, Ben Coman <btc(a)openinworld.com> wrote:
>
>> Shhh... The first rule of meta-club is we don't talk about meta-club.
>>
>>
>> cheers -ben
>>
>>
>> On Mon, Sep 25, 2017 at 11:09 PM, Guillermo Polito <
>> guillermopolito(a)gmail.com> wrote:
>>
>>> Why calling them meta-annotation and not just annotation? Annotations
>>> are in general already meta :)
>>>
>>> On Mon, Sep 25, 2017 at 5:01 PM, Denis Kudriashov <dionisiydk(a)gmail.com>
>>> wrote:
>>>
>>>> Hi.
>>>>
>>>> I glad to present one class package which introduces reusable mechanism
>>>> for first class annotations.
>>>>
>>>> The project can be found on github https://github.com/dion
>>>> isiydk/ClassMetaAnnotation.
>>>> And I tried to describe why it is needed in my blog
>>>> http://dionisiydk.blogspot.fr/2017/09/class-meta-annotations.html.
>>>>
>>>> And here is overview:
>>>>
>>>> Every annotation should be subclass of ClassMetaAnnotation. To attach
>>>> it to class you create new class side method which will return an instance
>>>> of the annotation. Method should be marked with pragma #classMetaAnnotation:
>>>>
>>>>
>>>> MyClass class>>specialAnnotation
>>>>
>>>> <classMetaAnnotation>
>>>>
>>>> ^MySpecialAnnotation new
>>>>
>>>>
>>>> To query annotations from system there are two methods:
>>>>
>>>> 1) You can ask concrete annotation class for all declared instances:
>>>>
>>>> MySpecialAnnotation declaredInstances
>>>>
>>>> 2) You can ask given class for all attached annotations:
>>>>
>>>> MyClass metaAnnotations
>>>>
>>>> Every annotation includes information about annotated class and the
>>>> selector of declaring method.
>>>> All annotations are cached. So it is cheap to query them. There are
>>>> extra messages to enumerate annotations using block.
>>>>
>>>> Now let's discuss it. I think it can be good addition for the Pharo 7.
>>>> Especially that it is very small code.
>>>>
>>>> Also I would like to thank Marcus who helps me realize this concept in
>>>> Commander and Calypso which I start simplify with this library.
>>>>
>>>> Best regards,
>>>> Denis
>>>>
>>>
>>>
>>>
>>> --
>>>
>>>
>>>
>>> Guille Polito
>>>
>>> Research Engineer
>>>
>>> Centre de Recherche en Informatique, Signal et Automatique de Lille
>>>
>>> CRIStAL - UMR 9189
>>>
>>> French National Center for Scientific Research - *http://www.cnrs.fr
>>> <http://www.cnrs.fr>*
>>>
>>>
>>> *Web:* *http://guillep.github.io* <http://guillep.github.io>
>>>
>>> *Phone: *+33 06 52 70 66 13 <+33%206%2052%2070%2066%2013>
>>>
>>
>>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
> On 28 Sep 2017, at 17:13, Thierry Goubier <thierry.goubier(a)gmail.com> wrote:
>
>
>
> 2017-09-28 17:08 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
>
>
> > On 28 Sep 2017, at 16:58, phil(a)highoctane.be wrote:
> >
> > I stand corrected.
> >
> > Nuclear style feature then.
> >
> > 'Let me get out of here {Smalltalk snapshot:false andQuit: true}. BOOM' interpolate
> >
> > Feels like
> >
> > STR='sudo reboot'; $(STR)
> >
> > in bash when one is sudoer.
>
> Yeah, but it is always the original programmer who writes the template (including the 'Smalltalk snapshot:false andQuit: true' and the 'sudo reboot' in you examples), you would not do that for any good reason.
>
> Typically, you would write something like
>
> 'My name is {firstname} {lastname}' interpolate.
>
> in a method of an object with firstname and lastname as instance variables. To access the binding, #evaluate: is used. Though a malicious person could enter 'Smalltalk snapshot:false andQuit: true' as name, it is not that expression that gets evaluated. So in that respect there is no risk.
>
> The risk would be when the template string itself would be (partially) based on used input.
>
> which is easy to overlook:
>
> aString interpolate
>
> People are on average a bit more carefull when they use #compile: or #evaluate:.
>
> Thierry
100% correct, hence my warning.
> > Phil
> >
> > On Thu, Sep 28, 2017 at 4:43 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> >
> >
> > > On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
> > >
> > > We also have http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/
> > >
> > > Phil
> >
> > Yes, Mustache is a cool templating engine, but it is similar to #format: not to #interpolate. With true string interpolation, you do not provide a context, you just write the expressions inline. Compare the following two:
> >
> > 'Today is {1} format: { Date today }.
> >
> > 'Today is { Date today }' interpolate.
> >
> > > On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> > > Hi,
> > >
> > > I got into a little office discussion about string interpolation as it is done in different programming languages.
> > >
> > > In Pharo we have String>>#format: which is pretty nice. It works as follows:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'x={1} and y={2}' format: { x. y }.
> > >
> > > It is also possible to use a dictionary with keys, like this:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
> > >
> > > But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
> > >
> > > Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
> > >
> > > => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
> > >
> > > Here is the implementation I came up with:
> > >
> > > String>>#interpolate
> > > "Format the receiver by interpolating the evaluation of expressions
> > > in between curly brackets in the context of the sender as in the following 3 oneline examples.
> > > 'Today is {Date today}' interpolate.
> > > | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> > > 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
> > >
> > > | senderContext |
> > > senderContext := thisContext sender.
> > > ^ self class new: self size streamContents: [ :out | | stream |
> > > stream := self readStream.
> > > [ stream atEnd ] whileFalse: [ | currentChar |
> > > (currentChar := stream next) == ${
> > > ifTrue: [ | expression result |
> > > expression := stream upTo: $}.
> > > result := Compiler new
> > > evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> > > out nextPutAll: result asString ]
> > > ifFalse: [
> > > currentChar == $\
> > > ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> > > ifFalse: [ out nextPut: currentChar ] ] ] ]
> > >
> > > It is a hack that could certainly be improved. And there is of course an obvious security problem.
> > >
> > > Thoughts ?
> > >
> > > Sven
> > >
> > >
> > >
> >
> >
> >
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Thierry Goubier
2017-09-28 17:08 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
>
>
> > On 28 Sep 2017, at 16:58, phil(a)highoctane.be wrote:
> >
> > I stand corrected.
> >
> > Nuclear style feature then.
> >
> > 'Let me get out of here {Smalltalk snapshot:false andQuit: true}. BOOM'
> interpolate
> >
> > Feels like
> >
> > STR='sudo reboot'; $(STR)
> >
> > in bash when one is sudoer.
>
> Yeah, but it is always the original programmer who writes the template
> (including the 'Smalltalk snapshot:false andQuit: true' and the 'sudo
> reboot' in you examples), you would not do that for any good reason.
>
> Typically, you would write something like
>
> 'My name is {firstname} {lastname}' interpolate.
>
> in a method of an object with firstname and lastname as instance
> variables. To access the binding, #evaluate: is used. Though a malicious
> person could enter 'Smalltalk snapshot:false andQuit: true' as name, it is
> not that expression that gets evaluated. So in that respect there is no
> risk.
>
> The risk would be when the template string itself would be (partially)
> based on used input.
>
which is easy to overlook:
aString interpolate
People are on average a bit more carefull when they use #compile: or
#evaluate:.
Thierry
>
> > Phil
> >
> > On Thu, Sep 28, 2017 at 4:43 PM, Sven Van Caekenberghe <sven(a)stfx.eu>
> wrote:
> >
> >
> > > On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
> > >
> > > We also have http://norbert.hartl.name/blog/2013/10/03/mustache-
> templates-for-smalltalk/
> > >
> > > Phil
> >
> > Yes, Mustache is a cool templating engine, but it is similar to #format:
> not to #interpolate. With true string interpolation, you do not provide a
> context, you just write the expressions inline. Compare the following two:
> >
> > 'Today is {1} format: { Date today }.
> >
> > 'Today is { Date today }' interpolate.
> >
> > > On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu>
> wrote:
> > > Hi,
> > >
> > > I got into a little office discussion about string interpolation as it
> is done in different programming languages.
> > >
> > > In Pharo we have String>>#format: which is pretty nice. It works as
> follows:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'x={1} and y={2}' format: { x. y }.
> > >
> > > It is also possible to use a dictionary with keys, like this:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
> > >
> > > But this is not true string interpolation as described in [
> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to
> write the value generating expressions directly inside the strings.
> > >
> > > Since in Pharo we add features not by extending the syntax but by
> adding messages I wondered if it could be done for string interpolation.
> The goal is to make the following work:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}'
> interpolate.
> > >
> > > => 'It seems x equals 123 and y equals foo while Pi is still
> 3.141592653589793'
> > >
> > > Here is the implementation I came up with:
> > >
> > > String>>#interpolate
> > > "Format the receiver by interpolating the evaluation of expressions
> > > in between curly brackets in the context of the sender as in the
> following 3 oneline examples.
> > > 'Today is {Date today}' interpolate.
> > > | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> > > 'In {#strings} you can escape \{ by prefixing it with \\'
> interpolate."
> > >
> > > | senderContext |
> > > senderContext := thisContext sender.
> > > ^ self class new: self size streamContents: [ :out | | stream |
> > > stream := self readStream.
> > > [ stream atEnd ] whileFalse: [ | currentChar |
> > > (currentChar := stream next) == ${
> > > ifTrue: [ | expression result |
> > > expression := stream upTo: $}.
> > > result := Compiler new
> > > evaluate: expression in: senderContext to: nil
> notifying: nil ifFail: [ ^ nil ] logged: false.
> > > out nextPutAll: result asString ]
> > > ifFalse: [
> > > currentChar == $\
> > > ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream
> next ] ]
> > > ifFalse: [ out nextPut: currentChar ] ] ] ]
> > >
> > > It is a hack that could certainly be improved. And there is of course
> an obvious security problem.
> > >
> > > Thoughts ?
> > >
> > > Sven
> > >
> > >
> > >
> >
> >
> >
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
> On 28 Sep 2017, at 16:55, Ron Teitelbaum <ron(a)usmedrec.com> wrote:
>
> Hi All,
>
> To solve this problem I do this:
>
> replaceTokensIn: aString
> ^self tokens inject: aString into: [:str :assoc |
> ((str explode: assoc key) mergeDelimited: assoc value value)].
>
> tokens is a collection of key value pairs.
>
> aString := 'Dear {!user}'.
>
> self tokens: {'{!user}' -> [self user]}.
>
> self replaceTokensIn: aString.
>
> I like using the blocks because they can be almost anything and since they are defined by the developer the security issue goes away. It's not a streaming solution which would be nice for a much longer text and it does rewrite the string for every token.
I think I understand what you mean. When there is no #evaluate: involved, there is no risk.
#explode: and #mergeDelimited: are not standard messages though ...
> On Thu, Sep 28, 2017 at 10:27 AM, phil(a)highoctane.be <phil(a)highoctane.be> wrote:
> We also have http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/
>
> Phil
>
> On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> Hi,
>
> I got into a little office discussion about string interpolation as it is done in different programming languages.
>
> In Pharo we have String>>#format: which is pretty nice. It works as follows:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={1} and y={2}' format: { x. y }.
>
> It is also possible to use a dictionary with keys, like this:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>
> But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
>
> Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
>
> | x y |
> x := 123.
> y := #foo.
> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
>
> => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
>
> Here is the implementation I came up with:
>
> String>>#interpolate
> "Format the receiver by interpolating the evaluation of expressions
> in between curly brackets in the context of the sender as in the following 3 oneline examples.
> 'Today is {Date today}' interpolate.
> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>
> | senderContext |
> senderContext := thisContext sender.
> ^ self class new: self size streamContents: [ :out | | stream |
> stream := self readStream.
> [ stream atEnd ] whileFalse: [ | currentChar |
> (currentChar := stream next) == ${
> ifTrue: [ | expression result |
> expression := stream upTo: $}.
> result := Compiler new
> evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> out nextPutAll: result asString ]
> ifFalse: [
> currentChar == $\
> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> ifFalse: [ out nextPut: currentChar ] ] ] ]
>
> It is a hack that could certainly be improved. And there is of course an obvious security problem.
>
> Thoughts ?
>
> Sven
>
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
> On 28 Sep 2017, at 16:58, phil(a)highoctane.be wrote:
>
> I stand corrected.
>
> Nuclear style feature then.
>
> 'Let me get out of here {Smalltalk snapshot:false andQuit: true}. BOOM' interpolate
>
> Feels like
>
> STR='sudo reboot'; $(STR)
>
> in bash when one is sudoer.
Yeah, but it is always the original programmer who writes the template (including the 'Smalltalk snapshot:false andQuit: true' and the 'sudo reboot' in you examples), you would not do that for any good reason.
Typically, you would write something like
'My name is {firstname} {lastname}' interpolate.
in a method of an object with firstname and lastname as instance variables. To access the binding, #evaluate: is used. Though a malicious person could enter 'Smalltalk snapshot:false andQuit: true' as name, it is not that expression that gets evaluated. So in that respect there is no risk.
The risk would be when the template string itself would be (partially) based on used input.
> Phil
>
> On Thu, Sep 28, 2017 at 4:43 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>
>
> > On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
> >
> > We also have http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/
> >
> > Phil
>
> Yes, Mustache is a cool templating engine, but it is similar to #format: not to #interpolate. With true string interpolation, you do not provide a context, you just write the expressions inline. Compare the following two:
>
> 'Today is {1} format: { Date today }.
>
> 'Today is { Date today }' interpolate.
>
> > On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> > Hi,
> >
> > I got into a little office discussion about string interpolation as it is done in different programming languages.
> >
> > In Pharo we have String>>#format: which is pretty nice. It works as follows:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'x={1} and y={2}' format: { x. y }.
> >
> > It is also possible to use a dictionary with keys, like this:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
> >
> > But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
> >
> > Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
> >
> > => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
> >
> > Here is the implementation I came up with:
> >
> > String>>#interpolate
> > "Format the receiver by interpolating the evaluation of expressions
> > in between curly brackets in the context of the sender as in the following 3 oneline examples.
> > 'Today is {Date today}' interpolate.
> > | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> > 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
> >
> > | senderContext |
> > senderContext := thisContext sender.
> > ^ self class new: self size streamContents: [ :out | | stream |
> > stream := self readStream.
> > [ stream atEnd ] whileFalse: [ | currentChar |
> > (currentChar := stream next) == ${
> > ifTrue: [ | expression result |
> > expression := stream upTo: $}.
> > result := Compiler new
> > evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> > out nextPutAll: result asString ]
> > ifFalse: [
> > currentChar == $\
> > ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> > ifFalse: [ out nextPut: currentChar ] ] ] ]
> >
> > It is a hack that could certainly be improved. And there is of course an obvious security problem.
> >
> > Thoughts ?
> >
> > Sven
> >
> >
> >
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by philļ¼ highoctane.be
I stand corrected.
Nuclear style feature then.
'Let me get out of here {Smalltalk snapshot:false andQuit: true}. BOOM'
interpolate
Feels like
STR='sudo reboot'; $(STR)
in bash when one is sudoer.
Phil
On Thu, Sep 28, 2017 at 4:43 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>
>
> > On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
> >
> > We also have http://norbert.hartl.name/blog/2013/10/03/mustache-
> templates-for-smalltalk/
> >
> > Phil
>
> Yes, Mustache is a cool templating engine, but it is similar to #format:
> not to #interpolate. With true string interpolation, you do not provide a
> context, you just write the expressions inline. Compare the following two:
>
> 'Today is {1} format: { Date today }.
>
> 'Today is { Date today }' interpolate.
>
> > On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu>
> wrote:
> > Hi,
> >
> > I got into a little office discussion about string interpolation as it
> is done in different programming languages.
> >
> > In Pharo we have String>>#format: which is pretty nice. It works as
> follows:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'x={1} and y={2}' format: { x. y }.
> >
> > It is also possible to use a dictionary with keys, like this:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
> >
> > But this is not true string interpolation as described in [
> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to
> write the value generating expressions directly inside the strings.
> >
> > Since in Pharo we add features not by extending the syntax but by adding
> messages I wondered if it could be done for string interpolation. The goal
> is to make the following work:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}'
> interpolate.
> >
> > => 'It seems x equals 123 and y equals foo while Pi is still
> 3.141592653589793'
> >
> > Here is the implementation I came up with:
> >
> > String>>#interpolate
> > "Format the receiver by interpolating the evaluation of expressions
> > in between curly brackets in the context of the sender as in the
> following 3 oneline examples.
> > 'Today is {Date today}' interpolate.
> > | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> > 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
> >
> > | senderContext |
> > senderContext := thisContext sender.
> > ^ self class new: self size streamContents: [ :out | | stream |
> > stream := self readStream.
> > [ stream atEnd ] whileFalse: [ | currentChar |
> > (currentChar := stream next) == ${
> > ifTrue: [ | expression result |
> > expression := stream upTo: $}.
> > result := Compiler new
> > evaluate: expression in: senderContext to: nil notifying:
> nil ifFail: [ ^ nil ] logged: false.
> > out nextPutAll: result asString ]
> > ifFalse: [
> > currentChar == $\
> > ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next
> ] ]
> > ifFalse: [ out nextPut: currentChar ] ] ] ]
> >
> > It is a hack that could certainly be improved. And there is of course an
> obvious security problem.
> >
> > Thoughts ?
> >
> > Sven
> >
> >
> >
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Ron Teitelbaum
Hi All,
To solve this problem I do this:
replaceTokensIn: aString
^self tokens inject: aString into: [:str :assoc |
((str explode: assoc key) mergeDelimited: assoc value value)].
tokens is a collection of key value pairs.
aString := 'Dear {!user}'.
self tokens: {'{!user}' -> [self user]}.
self replaceTokensIn: aString.
I like using the blocks because they can be almost anything and since they
are defined by the developer the security issue goes away. It's not a
streaming solution which would be nice for a much longer text and it does
rewrite the string for every token.
On Thu, Sep 28, 2017 at 10:27 AM, phil(a)highoctane.be <phil(a)highoctane.be>
wrote:
> We also have http://norbert.hartl.name/blog/2013/10/03/mustache-
> templates-for-smalltalk/
>
> Phil
>
> On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu>
> wrote:
>
>> Hi,
>>
>> I got into a little office discussion about string interpolation as it is
>> done in different programming languages.
>>
>> In Pharo we have String>>#format: which is pretty nice. It works as
>> follows:
>>
>> | x y |
>> x := 123.
>> y := #foo.
>> 'x={1} and y={2}' format: { x. y }.
>>
>> It is also possible to use a dictionary with keys, like this:
>>
>> | x y |
>> x := 123.
>> y := #foo.
>> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>>
>> But this is not true string interpolation as described in [
>> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to
>> write the value generating expressions directly inside the strings.
>>
>> Since in Pharo we add features not by extending the syntax but by adding
>> messages I wondered if it could be done for string interpolation. The goal
>> is to make the following work:
>>
>> | x y |
>> x := 123.
>> y := #foo.
>> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}'
>> interpolate.
>>
>> => 'It seems x equals 123 and y equals foo while Pi is still
>> 3.141592653589793'
>>
>> Here is the implementation I came up with:
>>
>> String>>#interpolate
>> "Format the receiver by interpolating the evaluation of expressions
>> in between curly brackets in the context of the sender as in the
>> following 3 oneline examples.
>> 'Today is {Date today}' interpolate.
>> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
>> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>>
>> | senderContext |
>> senderContext := thisContext sender.
>> ^ self class new: self size streamContents: [ :out | | stream |
>> stream := self readStream.
>> [ stream atEnd ] whileFalse: [ | currentChar |
>> (currentChar := stream next) == ${
>> ifTrue: [ | expression result |
>> expression := stream upTo: $}.
>> result := Compiler new
>> evaluate: expression in: senderContext to: nil notifying:
>> nil ifFail: [ ^ nil ] logged: false.
>> out nextPutAll: result asString ]
>> ifFalse: [
>> currentChar == $\
>> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next
>> ] ]
>> ifFalse: [ out nextPut: currentChar ] ] ] ]
>>
>> It is a hack that could certainly be improved. And there is of course an
>> obvious security problem.
>>
>> Thoughts ?
>>
>> Sven
>>
>>
>>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
Thierry,
> On 28 Sep 2017, at 16:38, Thierry Goubier <thierry.goubier(a)gmail.com> wrote:
>
> Hi Sven,
>
> Jason and Andrew wrote a string interpolation implementation for Andrew's language, Grace, in the parser. It works rather well and isn't too difficult to implement...
Like I said, I wanted to add the feature without changing the language (syntax). Using thisContext and the compiler makes that possible.
> The equivalent would be to add it to RB Parser, and, security wise, it would be as vulnerable as calling Compiler evaluate: 'an unsafe string'.
That is what I mean: it is an implicit #evaluate: call, the risk is comparable to an SQL injection attack if the attacker could write the template (not that likely though).
> Regards,
>
> Thierry
>
> 2017-09-28 16:20 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
> Hi,
>
> I got into a little office discussion about string interpolation as it is done in different programming languages.
>
> In Pharo we have String>>#format: which is pretty nice. It works as follows:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={1} and y={2}' format: { x. y }.
>
> It is also possible to use a dictionary with keys, like this:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>
> But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
>
> Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
>
> | x y |
> x := 123.
> y := #foo.
> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
>
> => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
>
> Here is the implementation I came up with:
>
> String>>#interpolate
> "Format the receiver by interpolating the evaluation of expressions
> in between curly brackets in the context of the sender as in the following 3 oneline examples.
> 'Today is {Date today}' interpolate.
> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>
> | senderContext |
> senderContext := thisContext sender.
> ^ self class new: self size streamContents: [ :out | | stream |
> stream := self readStream.
> [ stream atEnd ] whileFalse: [ | currentChar |
> (currentChar := stream next) == ${
> ifTrue: [ | expression result |
> expression := stream upTo: $}.
> result := Compiler new
> evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> out nextPutAll: result asString ]
> ifFalse: [
> currentChar == $\
> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> ifFalse: [ out nextPut: currentChar ] ] ] ]
>
> It is a hack that could certainly be improved. And there is of course an obvious security problem.
>
> Thoughts ?
>
> Sven
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
> On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
>
> We also have http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/
>
> Phil
Yes, Mustache is a cool templating engine, but it is similar to #format: not to #interpolate. With true string interpolation, you do not provide a context, you just write the expressions inline. Compare the following two:
'Today is {1} format: { Date today }.
'Today is { Date today }' interpolate.
> On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> Hi,
>
> I got into a little office discussion about string interpolation as it is done in different programming languages.
>
> In Pharo we have String>>#format: which is pretty nice. It works as follows:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={1} and y={2}' format: { x. y }.
>
> It is also possible to use a dictionary with keys, like this:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>
> But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
>
> Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
>
> | x y |
> x := 123.
> y := #foo.
> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
>
> => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
>
> Here is the implementation I came up with:
>
> String>>#interpolate
> "Format the receiver by interpolating the evaluation of expressions
> in between curly brackets in the context of the sender as in the following 3 oneline examples.
> 'Today is {Date today}' interpolate.
> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>
> | senderContext |
> senderContext := thisContext sender.
> ^ self class new: self size streamContents: [ :out | | stream |
> stream := self readStream.
> [ stream atEnd ] whileFalse: [ | currentChar |
> (currentChar := stream next) == ${
> ifTrue: [ | expression result |
> expression := stream upTo: $}.
> result := Compiler new
> evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> out nextPutAll: result asString ]
> ifFalse: [
> currentChar == $\
> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> ifFalse: [ out nextPut: currentChar ] ] ] ]
>
> It is a hack that could certainly be improved. And there is of course an obvious security problem.
>
> Thoughts ?
>
> Sven
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Thierry Goubier
Hi Sven,
Jason and Andrew wrote a string interpolation implementation for Andrew's
language, Grace, in the parser. It works rather well and isn't too
difficult to implement...
The equivalent would be to add it to RB Parser, and, security wise, it
would be as vulnerable as calling Compiler evaluate: 'an unsafe string'.
Regards,
Thierry
2017-09-28 16:20 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
> Hi,
>
> I got into a little office discussion about string interpolation as it is
> done in different programming languages.
>
> In Pharo we have String>>#format: which is pretty nice. It works as
> follows:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={1} and y={2}' format: { x. y }.
>
> It is also possible to use a dictionary with keys, like this:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>
> But this is not true string interpolation as described in [
> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to
> write the value generating expressions directly inside the strings.
>
> Since in Pharo we add features not by extending the syntax but by adding
> messages I wondered if it could be done for string interpolation. The goal
> is to make the following work:
>
> | x y |
> x := 123.
> y := #foo.
> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}'
> interpolate.
>
> => 'It seems x equals 123 and y equals foo while Pi is still
> 3.141592653589793'
>
> Here is the implementation I came up with:
>
> String>>#interpolate
> "Format the receiver by interpolating the evaluation of expressions
> in between curly brackets in the context of the sender as in the
> following 3 oneline examples.
> 'Today is {Date today}' interpolate.
> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>
> | senderContext |
> senderContext := thisContext sender.
> ^ self class new: self size streamContents: [ :out | | stream |
> stream := self readStream.
> [ stream atEnd ] whileFalse: [ | currentChar |
> (currentChar := stream next) == ${
> ifTrue: [ | expression result |
> expression := stream upTo: $}.
> result := Compiler new
> evaluate: expression in: senderContext to: nil notifying:
> nil ifFail: [ ^ nil ] logged: false.
> out nextPutAll: result asString ]
> ifFalse: [
> currentChar == $\
> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ]
> ]
> ifFalse: [ out nextPut: currentChar ] ] ] ]
>
> It is a hack that could certainly be improved. And there is of course an
> obvious security problem.
>
> Thoughts ?
>
> Sven
>
>
>
Sept. 28, 2017