Hello everyone. I see a lot of code that follows the following pattern: <a long expression> <aComplexTest> ifTrue: [ <a long expression> <something> ] ifFalse: [ <a long expression> <something else> ]. The classic refactoring is to store <a long expression> in a temp to avoid repetition: | temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ]. Then <a long expression> is evaluated once and the name of the temp can carry a meaningful name that helps reading the code. But this is more verbose than the first version. But if you add the following method in Object: if: conditionBlock then: trueBlock else: falseBlock ^ (conditionBlock cull: self) ifTrue: [ trueBlock cull: value ] ifFalse: [ falseBlock cull: value ] You can then rewrite it like that: <a long expression> if: [ :obj | obj <aComplexTest> ] then: [ :obj | <something> ] else: [ :obj | <something else> ] The names of the block args can give a meaningful name depending on the result of the test (something like ... if: #notEmpty then: [ :collection | ... ] else: [ :emptyCollection | ... ]). Using cull: for the three block also enable a good flexibility: you can omit the arg when irrelevant. Likewise, we could also have Object>>#while:do: while: conditionBlock do: actionBlock ^ [ conditionBlock cull: self ] whileTrue: [ actionBlock cull: self ] What do you think? Camille
is it not slower? and I would remove as much as method as possible from Object. why
| temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ].
is not good enough? And finally we should kill as much as possible of these ifâ¦. so
Hello everyone.
I see a lot of code that follows the following pattern:
<a long expression> <aComplexTest> ifTrue: [ <a long expression> <something> ] ifFalse: [ <a long expression> <something else> ].
The classic refactoring is to store <a long expression> in a temp to avoid repetition:
| temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ].
Then <a long expression> is evaluated once and the name of the temp can carry a meaningful name that helps reading the code. But this is more verbose than the first version. But if you add the following method in Object:
if: conditionBlock then: trueBlock else: falseBlock ^ (conditionBlock cull: self) ifTrue: [ trueBlock cull: value ] ifFalse: [ falseBlock cull: value ]
You can then rewrite it like that:
<a long expression> if: [ :obj | obj <aComplexTest> ] then: [ :obj | <something> ] else: [ :obj | <something else> ]
The names of the block args can give a meaningful name depending on the result of the test (something like ... if: #notEmpty then: [ :collection | ... ] else: [ :emptyCollection | ... ]). Using cull: for the three block also enable a good flexibility: you can omit the arg when irrelevant.
Likewise, we could also have Object>>#while:do:
while: conditionBlock do: actionBlock ^ [ conditionBlock cull: self ] whileTrue: [ actionBlock cull: self ]
What do you think?
Camille
On 18 juin 2013, at 11:10, Stéphane Ducasse wrote:
is it not slower?
Yes a bit slower.
and I would remove as much as method as possible from Object.
why
| temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ].
is not good enough?
If it is the whole content of a method it is good. But in complex methods you end up with a bunch of temps that do are not needed and that decrease readability.
And finally we should kill as much as possible of these ifâ¦. so
Hello everyone.
I see a lot of code that follows the following pattern:
<a long expression> <aComplexTest> ifTrue: [ <a long expression> <something> ] ifFalse: [ <a long expression> <something else> ].
The classic refactoring is to store <a long expression> in a temp to avoid repetition:
| temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ].
Then <a long expression> is evaluated once and the name of the temp can carry a meaningful name that helps reading the code. But this is more verbose than the first version. But if you add the following method in Object:
if: conditionBlock then: trueBlock else: falseBlock ^ (conditionBlock cull: self) ifTrue: [ trueBlock cull: value ] ifFalse: [ falseBlock cull: value ]
You can then rewrite it like that:
<a long expression> if: [ :obj | obj <aComplexTest> ] then: [ :obj | <something> ] else: [ :obj | <something else> ]
The names of the block args can give a meaningful name depending on the result of the test (something like ... if: #notEmpty then: [ :collection | ... ] else: [ :emptyCollection | ... ]). Using cull: for the three block also enable a good flexibility: you can omit the arg when irrelevant.
Likewise, we could also have Object>>#while:do:
while: conditionBlock do: actionBlock ^ [ conditionBlock cull: self ] whileTrue: [ actionBlock cull: self ]
What do you think?
Camille
Hi Camille, It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk : if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver. Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else: Regards, Thierry Le 18/06/2013 10:51, Camille Teruel a écrit :
Hello everyone.
I see a lot of code that follows the following pattern:
<a long expression> <aComplexTest> ifTrue: [ <a long expression> <something> ] ifFalse: [ <a long expression> <something else> ].
The classic refactoring is to store <a long expression> in a temp to avoid repetition:
| temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ].
Then <a long expression> is evaluated once and the name of the temp can carry a meaningful name that helps reading the code. But this is more verbose than the first version. But if you add the following method in Object:
if: conditionBlock then: trueBlock else: falseBlock ^ (conditionBlock cull: self) ifTrue: [ trueBlock cull: value ] ifFalse: [ falseBlock cull: value ]
You can then rewrite it like that:
<a long expression> if: [ :obj | obj <aComplexTest> ] then: [ :obj | <something> ] else: [ :obj | <something else> ]
The names of the block args can give a meaningful name depending on the result of the test (something like ... if: #notEmpty then: [ :collection | ... ] else: [ :emptyCollection | ... ]). Using cull: for the three block also enable a good flexibility: you can omit the arg when irrelevant.
Likewise, we could also have Object>>#while:do:
while: conditionBlock do: actionBlock ^ [ conditionBlock cull: self ] whileTrue: [ actionBlock cull: self ]
What do you think?
Camille
-- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
On 18 June 2013 11:20, Goubier Thierry <thierry.goubier@cea.fr> wrote:
Hi Camille,
It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk :
if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver.
Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else:
+1
Regards,
Thierry
Le 18/06/2013 10:51, Camille Teruel a écrit :
Hello everyone.
I see a lot of code that follows the following pattern:
<a long expression> <aComplexTest> ifTrue: [ <a long expression> <something> ] ifFalse: [ <a long expression> <something else> ].
The classic refactoring is to store <a long expression> in a temp to avoid repetition:
| temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ].
Then <a long expression> is evaluated once and the name of the temp can carry a meaningful name that helps reading the code. But this is more verbose than the first version. But if you add the following method in Object:
if: conditionBlock then: trueBlock else: falseBlock ^ (conditionBlock cull: self) ifTrue: [ trueBlock cull: value ] ifFalse: [ falseBlock cull: value ]
You can then rewrite it like that:
<a long expression> if: [ :obj | obj <aComplexTest> ] then: [ :obj | <something> ] else: [ :obj | <something else> ]
The names of the block args can give a meaningful name depending on the result of the test (something like ... if: #notEmpty then: [ :collection | ... ] else: [ :emptyCollection | ... ]). Using cull: for the three block also enable a good flexibility: you can omit the arg when irrelevant.
Likewise, we could also have Object>>#while:do:
while: conditionBlock do: actionBlock ^ [ conditionBlock cull: self ] whileTrue: [ actionBlock cull: self ]
What do you think?
Camille
-- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
-- Best regards, Igor Stasenko.
On 18 juin 2013, at 11:20, Goubier Thierry wrote:
Hi Camille,
It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk :
Ok the name may be confusing. So if you rename it to something like #if:do:elseDo:, it would be more smalltalkish and there is no confusion with classical if-then-else.
if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver.
Talking to an arbitrary object is the goal, since booleans are not very talkative kind of object. Compare | temp | temp := <complexExpression> temp isNil ifTrue: [...] ifFalse: [... temp ...] with: <complexExpression> ifNil: [ ... ] ifNotNil: [ :obj | ... obj ...] ifNil:ifNotNil: is not better only because it is shorter, it is better because I am talking to the object I am auditing, not a stupid boolean that knows nothing else but its truth value.
Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else:
I know this would break a long time tradition and people may not like it, so that's a question of taste and style, not understandability. There would be only one implementor, the implementation is really simple and the selector is explicit. Anyone can get use to it in less than 2 min. Do everyone verify the implementors of do: , collect: , ifTrue:ifFalse: ,... every time? No because people learned what they do when they learned Smalltalk, and I'm sure it didn't get them more than a few minutes.
Regards,
Thierry
Le 18/06/2013 10:51, Camille Teruel a écrit :
Hello everyone.
I see a lot of code that follows the following pattern:
<a long expression> <aComplexTest> ifTrue: [ <a long expression> <something> ] ifFalse: [ <a long expression> <something else> ].
The classic refactoring is to store <a long expression> in a temp to avoid repetition:
| temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ].
Then <a long expression> is evaluated once and the name of the temp can carry a meaningful name that helps reading the code. But this is more verbose than the first version. But if you add the following method in Object:
if: conditionBlock then: trueBlock else: falseBlock ^ (conditionBlock cull: self) ifTrue: [ trueBlock cull: value ] ifFalse: [ falseBlock cull: value ]
You can then rewrite it like that:
<a long expression> if: [ :obj | obj <aComplexTest> ] then: [ :obj | <something> ] else: [ :obj | <something else> ]
The names of the block args can give a meaningful name depending on the result of the test (something like ... if: #notEmpty then: [ :collection | ... ] else: [ :emptyCollection | ... ]). Using cull: for the three block also enable a good flexibility: you can omit the arg when irrelevant.
Likewise, we could also have Object>>#while:do:
while: conditionBlock do: actionBlock ^ [ conditionBlock cull: self ] whileTrue: [ actionBlock cull: self ]
What do you think?
Camille
-- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
Le 18/06/2013 12:27, Camille Teruel a écrit :
On 18 juin 2013, at 11:20, Goubier Thierry wrote:
Hi Camille,
It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk :
Ok the name may be confusing. So if you rename it to something like #if:do:elseDo:, it would be more smalltalkish and there is no confusion with classical if-then-else.
Maybe, that would help.
if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver.
Talking to an arbitrary object is the goal, since booleans are not very talkative kind of object. Compare
| temp | temp := <complexExpression> temp isNil ifTrue: [...] ifFalse: [... temp ...]
with:
<complexExpression> ifNil: [ ... ] ifNotNil: [ :obj | ... obj ...]
ifNil:ifNotNil: is not better only because it is shorter, it is better because I am talking to the object I am auditing, not a stupid boolean that knows nothing else but its truth value.
Yes, but I know firsthand (because I used Smalltalk before that idiom was introduced) that it represent one more idiom to learn, and it's still not familiar. The same goes with withStreamDo: or what is that idiom again I sometimes encounter.
Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else:
I know this would break a long time tradition and people may not like it, so that's a question of taste and style, not understandability. There would be only one implementor, the implementation is really simple and the selector is explicit.
Anyone can get use to it in less than 2 min.
It's one more thing to get used to and to explain to beginners in say 10 minutes per idiom... (describe, give an example, let them practice, rinse and repeat for each idiom). Add all the new idioms and, instead of explaining Smalltalk in half a day, you spend a few days doing explaining all those idioms and not doing more interesting stuff. Soon, you end up like ocaml, where your minimum introduction time is a week, not half a day.
Do everyone verify the implementors of do: , collect: , ifTrue:ifFalse: ,... every time?
No because people learned what they do when they learned Smalltalk, and I'm sure it didn't get them more than a few minutes.
Yes, but add the ifNil: ifNotNil:, stream thingies I never remember, your variant of if-else, and, and ... On some of those, I have to look for the implementors, and I'm really happy to benefit from the smart suggestions in the new browsers. (Additionally, code patterns using cull: in pharo more often than not are very poorly documented about the arguments that are given to the block). Smalltalk is disruptive enough as it is (and still is after all those years) to try not to make it more complex. I'd prefer efforts making obvious really complex patterns instead of idioms with a not so great cognitive load to effectiveness. I'd be happy to have a shorter list of methods and extensions on Object, as well :) Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
I do not like it :) also, you already have #in: which is more generic and allows simplifications: <my complex expression> in: [ :blah | blah = myTest ifTrue: [ blah some ] ] ifFalse: [ blah other ] ] and also the advantage is that you are not restricted to #ifTrue:ifFalse: Esteban On Jun 18, 2013, at 1:05 PM, Goubier Thierry <thierry.goubier@cea.fr> wrote:
Le 18/06/2013 12:27, Camille Teruel a écrit :
On 18 juin 2013, at 11:20, Goubier Thierry wrote:
Hi Camille,
It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk :
Ok the name may be confusing. So if you rename it to something like #if:do:elseDo:, it would be more smalltalkish and there is no confusion with classical if-then-else.
Maybe, that would help.
if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver.
Talking to an arbitrary object is the goal, since booleans are not very talkative kind of object. Compare
| temp | temp := <complexExpression> temp isNil ifTrue: [...] ifFalse: [... temp ...]
with:
<complexExpression> ifNil: [ ... ] ifNotNil: [ :obj | ... obj ...]
ifNil:ifNotNil: is not better only because it is shorter, it is better because I am talking to the object I am auditing, not a stupid boolean that knows nothing else but its truth value.
Yes, but I know firsthand (because I used Smalltalk before that idiom was introduced) that it represent one more idiom to learn, and it's still not familiar.
The same goes with withStreamDo: or what is that idiom again I sometimes encounter.
Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else:
I know this would break a long time tradition and people may not like it, so that's a question of taste and style, not understandability. There would be only one implementor, the implementation is really simple and the selector is explicit.
Anyone can get use to it in less than 2 min.
It's one more thing to get used to and to explain to beginners in say 10 minutes per idiom... (describe, give an example, let them practice, rinse and repeat for each idiom).
Add all the new idioms and, instead of explaining Smalltalk in half a day, you spend a few days doing explaining all those idioms and not doing more interesting stuff.
Soon, you end up like ocaml, where your minimum introduction time is a week, not half a day.
Do everyone verify the implementors of do: , collect: , ifTrue:ifFalse: ,... every time?
No because people learned what they do when they learned Smalltalk, and I'm sure it didn't get them more than a few minutes.
Yes, but add the ifNil: ifNotNil:, stream thingies I never remember, your variant of if-else, and, and ... On some of those, I have to look for the implementors, and I'm really happy to benefit from the smart suggestions in the new browsers. (Additionally, code patterns using cull: in pharo more often than not are very poorly documented about the arguments that are given to the block).
Smalltalk is disruptive enough as it is (and still is after all those years) to try not to make it more complex. I'd prefer efforts making obvious really complex patterns instead of idioms with a not so great cognitive load to effectiveness.
I'd be happy to have a shorter list of methods and extensions on Object, as well :)
Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
On 18 juin 2013, at 13:09, Esteban Lorenzano wrote:
I do not like it :) I understand that (especially from a conservative who doesn't even like colors ;D ).
also, you already have #in: which is more generic and allows simplifications:
<my complex expression> in: [ :blah | blah = myTest ifTrue: [ blah some ] ] ifFalse: [ blah other ] ]
and also the advantage is that you are not restricted to #ifTrue:ifFalse:
Yes I love #in: , that was my inspiration. if:do:, if:do:elseDo: and while:do: would just be a bit of sugar to use sparingly just like in:.
Esteban
On Jun 18, 2013, at 1:05 PM, Goubier Thierry <thierry.goubier@cea.fr> wrote:
Le 18/06/2013 12:27, Camille Teruel a écrit :
On 18 juin 2013, at 11:20, Goubier Thierry wrote:
Hi Camille,
It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk :
Ok the name may be confusing. So if you rename it to something like #if:do:elseDo:, it would be more smalltalkish and there is no confusion with classical if-then-else.
Maybe, that would help.
if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver.
Talking to an arbitrary object is the goal, since booleans are not very talkative kind of object. Compare
| temp | temp := <complexExpression> temp isNil ifTrue: [...] ifFalse: [... temp ...]
with:
<complexExpression> ifNil: [ ... ] ifNotNil: [ :obj | ... obj ...]
ifNil:ifNotNil: is not better only because it is shorter, it is better because I am talking to the object I am auditing, not a stupid boolean that knows nothing else but its truth value.
Yes, but I know firsthand (because I used Smalltalk before that idiom was introduced) that it represent one more idiom to learn, and it's still not familiar.
The same goes with withStreamDo: or what is that idiom again I sometimes encounter.
Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else:
I know this would break a long time tradition and people may not like it, so that's a question of taste and style, not understandability. There would be only one implementor, the implementation is really simple and the selector is explicit.
Anyone can get use to it in less than 2 min.
It's one more thing to get used to and to explain to beginners in say 10 minutes per idiom... (describe, give an example, let them practice, rinse and repeat for each idiom).
Add all the new idioms and, instead of explaining Smalltalk in half a day, you spend a few days doing explaining all those idioms and not doing more interesting stuff.
Soon, you end up like ocaml, where your minimum introduction time is a week, not half a day.
Do everyone verify the implementors of do: , collect: , ifTrue:ifFalse: ,... every time?
No because people learned what they do when they learned Smalltalk, and I'm sure it didn't get them more than a few minutes.
Yes, but add the ifNil: ifNotNil:, stream thingies I never remember, your variant of if-else, and, and ... On some of those, I have to look for the implementors, and I'm really happy to benefit from the smart suggestions in the new browsers. (Additionally, code patterns using cull: in pharo more often than not are very poorly documented about the arguments that are given to the block).
Smalltalk is disruptive enough as it is (and still is after all those years) to try not to make it more complex. I'd prefer efforts making obvious really complex patterns instead of idioms with a not so great cognitive load to effectiveness.
I'd be happy to have a shorter list of methods and extensions on Object, as well :)
Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
I never heard of that, it is cool, Esteban ! There are not many senders though. Thx, Sven On 18 Jun 2013, at 13:09, Esteban Lorenzano <estebanlm@gmail.com> wrote:
I do not like it :)
also, you already have #in: which is more generic and allows simplifications:
<my complex expression> in: [ :blah | blah = myTest ifTrue: [ blah some ] ] ifFalse: [ blah other ] ]
and also the advantage is that you are not restricted to #ifTrue:ifFalse:
Esteban
On Jun 18, 2013, at 1:05 PM, Goubier Thierry <thierry.goubier@cea.fr> wrote:
Le 18/06/2013 12:27, Camille Teruel a écrit :
On 18 juin 2013, at 11:20, Goubier Thierry wrote:
Hi Camille,
It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk :
Ok the name may be confusing. So if you rename it to something like #if:do:elseDo:, it would be more smalltalkish and there is no confusion with classical if-then-else.
Maybe, that would help.
if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver.
Talking to an arbitrary object is the goal, since booleans are not very talkative kind of object. Compare
| temp | temp := <complexExpression> temp isNil ifTrue: [...] ifFalse: [... temp ...]
with:
<complexExpression> ifNil: [ ... ] ifNotNil: [ :obj | ... obj ...]
ifNil:ifNotNil: is not better only because it is shorter, it is better because I am talking to the object I am auditing, not a stupid boolean that knows nothing else but its truth value.
Yes, but I know firsthand (because I used Smalltalk before that idiom was introduced) that it represent one more idiom to learn, and it's still not familiar.
The same goes with withStreamDo: or what is that idiom again I sometimes encounter.
Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else:
I know this would break a long time tradition and people may not like it, so that's a question of taste and style, not understandability. There would be only one implementor, the implementation is really simple and the selector is explicit.
Anyone can get use to it in less than 2 min.
It's one more thing to get used to and to explain to beginners in say 10 minutes per idiom... (describe, give an example, let them practice, rinse and repeat for each idiom).
Add all the new idioms and, instead of explaining Smalltalk in half a day, you spend a few days doing explaining all those idioms and not doing more interesting stuff.
Soon, you end up like ocaml, where your minimum introduction time is a week, not half a day.
Do everyone verify the implementors of do: , collect: , ifTrue:ifFalse: ,... every time?
No because people learned what they do when they learned Smalltalk, and I'm sure it didn't get them more than a few minutes.
Yes, but add the ifNil: ifNotNil:, stream thingies I never remember, your variant of if-else, and, and ... On some of those, I have to look for the implementors, and I'm really happy to benefit from the smart suggestions in the new browsers. (Additionally, code patterns using cull: in pharo more often than not are very poorly documented about the arguments that are given to the block).
Smalltalk is disruptive enough as it is (and still is after all those years) to try not to make it more complex. I'd prefer efforts making obvious really complex patterns instead of idioms with a not so great cognitive load to effectiveness.
I'd be happy to have a shorter list of methods and extensions on Object, as well :)
Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
Le 18/06/2013 13:09, Esteban Lorenzano a écrit :
I do not like it :)
also, you already have #in: which is more generic and allows simplifications:
<my complex expression> in: [ :blah | blah = myTest ifTrue: [ blah some ] ] ifFalse: [ blah other ] ]
This is cool :) Didn't knew about this one. Could we use do: in the same way ? Because in: is in a way the same as {<my complex expression>} do: [ :blah | blah = myTest ifTrue: [ blah some ] ifFalse: [ blah other ] ] With a different return value. Thierry
and also the advantage is that you are not restricted to #ifTrue:ifFalse:
Esteban
On Jun 18, 2013, at 1:05 PM, Goubier Thierry <thierry.goubier@cea.fr> wrote:
Le 18/06/2013 12:27, Camille Teruel a écrit :
On 18 juin 2013, at 11:20, Goubier Thierry wrote:
Hi Camille,
It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk :
Ok the name may be confusing. So if you rename it to something like #if:do:elseDo:, it would be more smalltalkish and there is no confusion with classical if-then-else.
Maybe, that would help.
if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver.
Talking to an arbitrary object is the goal, since booleans are not very talkative kind of object. Compare
| temp | temp := <complexExpression> temp isNil ifTrue: [...] ifFalse: [... temp ...]
with:
<complexExpression> ifNil: [ ... ] ifNotNil: [ :obj | ... obj ...]
ifNil:ifNotNil: is not better only because it is shorter, it is better because I am talking to the object I am auditing, not a stupid boolean that knows nothing else but its truth value.
Yes, but I know firsthand (because I used Smalltalk before that idiom was introduced) that it represent one more idiom to learn, and it's still not familiar.
The same goes with withStreamDo: or what is that idiom again I sometimes encounter.
Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else:
I know this would break a long time tradition and people may not like it, so that's a question of taste and style, not understandability. There would be only one implementor, the implementation is really simple and the selector is explicit.
Anyone can get use to it in less than 2 min.
It's one more thing to get used to and to explain to beginners in say 10 minutes per idiom... (describe, give an example, let them practice, rinse and repeat for each idiom).
Add all the new idioms and, instead of explaining Smalltalk in half a day, you spend a few days doing explaining all those idioms and not doing more interesting stuff.
Soon, you end up like ocaml, where your minimum introduction time is a week, not half a day.
Do everyone verify the implementors of do: , collect: , ifTrue:ifFalse: ,... every time?
No because people learned what they do when they learned Smalltalk, and I'm sure it didn't get them more than a few minutes.
Yes, but add the ifNil: ifNotNil:, stream thingies I never remember, your variant of if-else, and, and ... On some of those, I have to look for the implementors, and I'm really happy to benefit from the smart suggestions in the new browsers. (Additionally, code patterns using cull: in pharo more often than not are very poorly documented about the arguments that are given to the block).
Smalltalk is disruptive enough as it is (and still is after all those years) to try not to make it more complex. I'd prefer efforts making obvious really complex patterns instead of idioms with a not so great cognitive load to effectiveness.
I'd be happy to have a shorter list of methods and extensions on Object, as well :)
Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
-- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
On 18 June 2013 12:35, Goubier Thierry <thierry.goubier@cea.fr> wrote:
Le 18/06/2013 13:09, Esteban Lorenzano a écrit :
I do not like it :)
also, you already have #in: which is more generic and allows simplifications:
<my complex expression> in: [ :blah | blah = myTest ifTrue: [ blah some ] ] ifFalse: [ blah other ] ]
This is cool :) Didn't knew about this one.
It's a lot like `let` in other languages (Haskell, the Lisps, and so on).
Could we use do: in the same way ? Because in: is in a way the same as
{<my complex expression>} do: [ :blah |
blah = myTest ifTrue: [ blah some ] ifFalse: [ blah other ] ]
With a different return value.
No: #do: signals that you're doing something entirely for a side effect. But if you said `{<my complex expression} collect: [:blah | ...]` then I'd agree with you.
Thierry
and also the advantage is that you are not restricted to #ifTrue:ifFalse:
Esteban
On Jun 18, 2013, at 1:05 PM, Goubier Thierry <thierry.goubier@cea.fr> wrote:
Le 18/06/2013 12:27, Camille Teruel a écrit :
On 18 juin 2013, at 11:20, Goubier Thierry wrote:
Hi Camille,
It's not bad as things goes, because it does look a bit like non-smalltalk code (i.e. the if then else structure) except that the precise meaning is very much Smalltalk :
Ok the name may be confusing. So if you rename it to something like #if:do:elseDo:, it would be more smalltalkish and there is no confusion with classical if-then-else.
Maybe, that would help.
if: has a receiver, and there is a not so intuitive relationship between the bloc parameters and the receiver.
Talking to an arbitrary object is the goal, since booleans are not very talkative kind of object. Compare
| temp | temp := <complexExpression> temp isNil ifTrue: [...] ifFalse: [... temp ...]
with:
<complexExpression> ifNil: [ ... ] ifNotNil: [ :obj | ... obj ...]
ifNil:ifNotNil: is not better only because it is shorter, it is better because I am talking to the object I am auditing, not a stupid boolean that knows nothing else but its truth value.
Yes, but I know firsthand (because I used Smalltalk before that idiom was introduced) that it represent one more idiom to learn, and it's still not familiar.
The same goes with withStreamDo: or what is that idiom again I sometimes encounter.
Honestly, as far as code reviews goes, I'll prefer the temp refactoring. Understandable without having to search for the implementors of #if:then:else:
I know this would break a long time tradition and people may not like it, so that's a question of taste and style, not understandability. There would be only one implementor, the implementation is really simple and the selector is explicit.
Anyone can get use to it in less than 2 min.
It's one more thing to get used to and to explain to beginners in say 10 minutes per idiom... (describe, give an example, let them practice, rinse and repeat for each idiom).
Add all the new idioms and, instead of explaining Smalltalk in half a day, you spend a few days doing explaining all those idioms and not doing more interesting stuff.
Soon, you end up like ocaml, where your minimum introduction time is a week, not half a day.
Do everyone verify the implementors of do: , collect: , ifTrue:ifFalse: ,... every time?
No because people learned what they do when they learned Smalltalk, and I'm sure it didn't get them more than a few minutes.
Yes, but add the ifNil: ifNotNil:, stream thingies I never remember, your variant of if-else, and, and ... On some of those, I have to look for the implementors, and I'm really happy to benefit from the smart suggestions in the new browsers. (Additionally, code patterns using cull: in pharo more often than not are very poorly documented about the arguments that are given to the block).
Smalltalk is disruptive enough as it is (and still is after all those years) to try not to make it more complex. I'd prefer efforts making obvious really complex patterns instead of idioms with a not so great cognitive load to effectiveness.
I'd be happy to have a shorter list of methods and extensions on Object, as well :)
Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
-- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
Le 18/06/2013 13:41, Frank Shearar a écrit :
On 18 June 2013 12:35, Goubier Thierry <thierry.goubier@cea.fr> wrote:
Le 18/06/2013 13:09, Esteban Lorenzano a écrit :
I do not like it :)
also, you already have #in: which is more generic and allows simplifications:
<my complex expression> in: [ :blah | blah = myTest ifTrue: [ blah some ] ] ifFalse: [ blah other ] ]
This is cool :) Didn't knew about this one.
It's a lot like `let` in other languages (Haskell, the Lisps, and so on).
Yes, of course, but I was nicely surprised to see it here :)
Could we use do: in the same way ? Because in: is in a way the same as
{<my complex expression>} do: [ :blah |
blah = myTest ifTrue: [ blah some ] ifFalse: [ blah other ] ]
With a different return value.
No: #do: signals that you're doing something entirely for a side effect. But if you said `{<my complex expression} collect: [:blah | ...]` then I'd agree with you.
Yes. I'd even use`({<my complex expression>} collect: [:blah |
...]) first` just to be sure !
Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95
What I think. Well the point of Smalltalk is that it offers you a language that allows you to play with the syntax. Thats pretty much the heart of Smalltalk. So I would definitely not be against offering an alternative to if conditions. Personally I have no problem with the original syntax. I would not use temp variables I would instead create methods that returned those blocks. This way I hide away verbosity of code and the user can easily browse those blocks using the IDE. Its definitely a good thing to explore alternative ways of doing things. However smalltalk coders should not be afraid to introduce new language features that may seem weird. If the documentation is good , people wont have a hard time understand it unless its a really complex feature. I am very new to smalltalk I found blocks a lot more strange than ifTrue:/ifFalse: yet it did not take me more than 2 minutes to figure things out. Of course maybe there is even a better alternative than what you offer and what standard syntax already offers out there, waiting to be found ;) -- View this message in context: http://forum.world.st/Pharo-dev-Object-if-then-else-tp4693871p4693889.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
IMO the most important consideration should be readability: one should be able to guess what the method does without having to look how it is implemented, which means that the naming is crucial. To me *personally* it is not intuitive what is meant by *anObject if: aBlockOrSelector do: aBlock elseDo: anotherBlock*. It is no clearer to me than *if:then:else:* To really be clear I would prefer something like *anObject ifEvaluatesToTrueUsing: aBlockOrSelector then: aBlock else: anotherBlock*. Now there's no guesswork involved, and the code is readable to anyone. Just my $0.02 ;-) On Tue, Jun 18, 2013 at 1:35 PM, kilon <thekilon@yahoo.co.uk> wrote:
What I think. Well the point of Smalltalk is that it offers you a language that allows you to play with the syntax. Thats pretty much the heart of Smalltalk. So I would definitely not be against offering an alternative to if conditions.
Personally I have no problem with the original syntax. I would not use temp variables I would instead create methods that returned those blocks. This way I hide away verbosity of code and the user can easily browse those blocks using the IDE.
Its definitely a good thing to explore alternative ways of doing things. However smalltalk coders should not be afraid to introduce new language features that may seem weird. If the documentation is good , people wont have a hard time understand it unless its a really complex feature.
I am very new to smalltalk I found blocks a lot more strange than ifTrue:/ifFalse: yet it did not take me more than 2 minutes to figure things out. Of course maybe there is even a better alternative than what you offer and what standard syntax already offers out there, waiting to be found ;)
-- View this message in context: http://forum.world.st/Pharo-dev-Object-if-then-else-tp4693871p4693889.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Cheers,
ifEvaluatesToTrueUsing sounds like an overkill to me and unnecessary , its common convention in all popular languages than an if always needs to evaluate to true to execute and if it evaluates to false then "else" handles it. -- View this message in context: http://forum.world.st/Pharo-dev-Object-if-then-else-tp4693871p4693945.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
I still believe all of that is unnecessary sugar, that ends been more annoying than helpful. no matter the name we choose :) On Jun 18, 2013, at 3:53 PM, kilon <thekilon@yahoo.co.uk> wrote:
ifEvaluatesToTrueUsing sounds like an overkill to me and unnecessary , its common convention in all popular languages than an if always needs to evaluate to true to execute and if it evaluates to false then "else" handles it.
-- View this message in context: http://forum.world.st/Pharo-dev-Object-if-then-else-tp4693871p4693945.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
Very few things are truly necessary in life, programming languages are not amongst them. As I said , for me how already things work in pharo is fine concerning ifTrue: and friends . -- View this message in context: http://forum.world.st/Pharo-dev-Object-if-then-else-tp4693871p4693952.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
I don't like this new structure. Then people coming from non object language using all the time control structure will do : #someRandomObject if: then: else: thinking of doing a C style condition and not using at all the receiver. I like how it is now. 2013/6/18 kilon <thekilon@yahoo.co.uk>
Very few things are truly necessary in life, programming languages are not amongst them.
As I said , for me how already things work in pharo is fine concerning ifTrue: and friends .
-- View this message in context: http://forum.world.st/Pharo-dev-Object-if-then-else-tp4693871p4693952.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Clément Béra Mate Virtual Machine Engineer Bâtiment B 40, avenue Halley 59650 *Villeneuve d'Ascq*
On 18 juin 2013, at 17:04, Clément Bera wrote:
I don't like this new structure. Then people coming from non object language using all the time control structure will do :
#someRandomObject if: then: else: thinking of doing a C style condition and not using at all the receiver.
Come on, people are not that stupid ! And if they really are, no matter what you do, they will write bad code eventually.
I like how it is now.
It is not about replacing stuff, just adding one method. ifTrue:ifFalse: is still the better choice in most situations.
2013/6/18 kilon <thekilon@yahoo.co.uk> Very few things are truly necessary in life, programming languages are not amongst them.
As I said , for me how already things work in pharo is fine concerning ifTrue: and friends .
-- View this message in context: http://forum.world.st/Pharo-dev-Object-if-then-else-tp4693871p4693952.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Clément Béra Mate Virtual Machine Engineer Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
Le 18/06/2013 18:53, Camille Teruel a écrit :
#someRandomObject if: then: else: thinking of doing a C style condition and not using at all the receiver.
Come on, people are not that stupid ! And if they really are, no matter what you do, they will write bad code eventually.
It is not a matter of stupidy but analogy as this is the way the brain works. People with C knolwdge will make these mistakes, transposing their C knowloedge to the Smalltak. I did that mistakes. Hilaire -- Dr. Geo http://drgeo.eu
It feels to me as if this code wants to be on the temp. So perhaps,
| temp | temp := <a long expression>. temp <aComplexTest> ifTrue: [ temp <something> ] ifFalse: [ temp <something else> ].
can become <a long expression> doSomething and on Temp: doSomething self <aComplexTest> ifTrue: [ self <something> ] ifFalse: [ self <something else> ] It often works out nicer if you move the code around closer to where it belongs. Make <a long expression> a method somewhere and it may end up being simpler. my2c
participants (12)
-
Camille Teruel -
Clément Bera -
Esteban Lorenzano -
Frank Shearar -
Goubier Thierry -
Hilaire Fernandes -
Igor Stasenko -
kilon -
Otto Behrens -
Peter Hugosson-Miller -
Stéphane Ducasse -
Sven Van Caekenberghe