Re: [Pharo-users] Set >> collect:thenDo:

2019-09-09 Thread Richard O'Keefe
An automatic refactoring rule that converts
  (a collect: b) do: c
to
  (a collect: b thenDo: c)
would change the semantics of the code in all of
Squeak, Pharo, and Smalltalk/X, whichever definition
of #collect:thenDo: is taken, and in Squeak would
make the code slower, not faster.

Using a different name *would* reduce confusion.

However, there is an alternative.
My library copied the #virtual{Collect,Select,Reject}:
interface from Strongtalk.  As the comment puts it,
 The idea is to do #select:, #reject:, #collect:, and some
 other collection->collection operations lazily.  As long
 as you just use #do: , the operations will be referred
 back to the original collection, so that there is less
 need for fusion methods like #select:thenCollect:.
 ...
 You can do
 coll
virtualSelect: [..])
virtualCollect: [...])
virtualSelect: [..])
virtualCollect: [...])
  asCollection
  and only *one* new collection is actually built.

So
  (aCollection virtualCollect: transformBlock)
do: actionBlock
*does* build an intermediate object (with two instance
variables) but *doesn't* build a whole intermediate
collection.  And that combination *could* be fused by
an automatic rule without breaking anything.

Does that sound like a way forward?
I could convert my implementation of this interface to
Pharo if people would like me to.


On Tue, 10 Sep 2019 at 01:51, Steffen Märcker  wrote:

> I think this thread indicates that the selector #collect:thenDo: may
> indeed cause some missunderstanding given standard semantics of #collect:.
> Is there any reason not to use a different one, such as #map:thenDo:, to
> make the difference clearer?
>
> A nice side effect could be a new automatic refactoring rule that
> consolidates chained #collect: and #do: sends into a faster
> #collect:thenDo: send without breaking existing code.
>
> Am .09.2019, 07:46 Uhr, schrieb Richard O'Keefe :
>
> > (1) If you want (aSet collect: collectBlock) do: doBlock
> > you can write exactly that.  Nothing stops you, and it will
> > be as clear and reliable as any use of Set>>collect:, which
> > is to say NOT VERY CLEAR OR RELIABLE AT ALL.
> >
> > (2) #collect:then{Do:Select:Reject:} had no other purpose than
> > to avoid creating an intermediate and otherwise useless
> > collection.  If you are not trying to involve an intermediate
> > set then it just plain wrong to use #collect:thenDo:.
> >
> > (3) Oddly enough, the reason that #collect:thenDo: exists in my
> > library is that I copied it from Squeak, at a time when it had
> > the same definition as Pharo and ST/X.  Had I known of the change
> > in Squeak I would have bitterly opposed it.  The comment in the
> > current Squeak code, that it is for readability, is 100% the
> > reverse of the truth.  Using the version with parentheses is WAY
> > clearer than using the portmanteau method.  Sigh.  I see they
> > broke #collect:thenSelect: in the same way.
> >
> > (4) Let me offer you another member of the #collect:then* family.
> >
> > Collection
> >   collect: collectBlock thenInject: initial into: injectBlock
> > |r|
> > r := initial.
> > self do: [:each |
> >   r := injectBlock value: r value: (collectBlock value: each)].
> > ^r
> >
> > #(now is the hour for us to say goodbye) asSet
> >   collect: [:each | each size]
> >   thenInject: 0 into: [:acc :each | acc + each]
> >  => 29
> > (#(now is the hour for us to say goodbye) asSet
> >   collect: [:each | each size])
> >   inject: 0 into: [:acc :each | acc + each]
> >  => 16
> >
> >That is, it would be WRONG to implement #collect:thenInject:into:
> >as #collect: followed by #inject:into:.  The point is NOT to
> >coalesce things that the receiver might (in general, incorrectly)
> >regard as equal.
> >
> > (5) The bottom line is that if #collect:thenDo: and its relatives did
> > not have their present semantics in Pharo (and ST/X), they would
> > need to be reinvented, with names that were not as clear.
> >
> > (1) Just to repeat for emphasis, if you *want* (_ collect: _) do: _
> > then that is exactly what you should write.  There is no
> > excuse for using #collect:thenDo: in that case.  It is NOT
> > clearer to do so.  And you should imagine me jumping up and
> > down screaming that sending #collect: to a set is a bad code
> > smell which demands very explicit documentation as to why you
> > (for example) want a Set to answer a Set but an IdentitySet
> > to also answer a Set, not the expected IdentitySet.  (I have
> > been bitten by that more than once.)
> >
> >
> >
> > On Mon, 9 Sep 2019 at 01:33, Herby Vojčík  wrote:
> >
> >> On 8. 9. 2019 14:28, Peter Kenny wrote:
> >> > Two comments:
> >> > First, the method comment for Collection>>collect:thenDo: is "Utility
> >> method
> >> > to improve readability", 

Re: [Pharo-users] Set >> collect:thenDo:

2019-09-09 Thread Richard O'Keefe
Digging a bit further, the change from the pointless implementation to
the current implementation was made between Pharo 2.0 and Pharo 3.0
and the current definition was introduced into ST/X some time between
2010 and 2012, which is about the same time as Pharo.
{collect,select,reject}:thenDo: were added to my library on
2004.09.14, exactly a day after the version now in Squeak.  Which
leads me to believe that I picked the method up from a previous
version of Squeak and that some of the Squeak version history has
been lost.

By the way, it's not just Sets where the current Squeak definition is
a pain in the posterior.  Consider the following example.

  |o|
  o := OrderedCollection new.
  #[3 1 4 1 5 9]
collect: [:byte | byte asFloat]
thenDo: [:float | o addLast: float].
  Transcript print: o; cr.

This works fine in Pharo, in Smalltalk/X, and in my library.
It raises an exception in Squeak.
Or try

   #[3 1 4 1 5 9]
 collect: [:byte | byte odd ifTrue: [byte printString]
ifFalse: [byte]]
 thenSelect: [:each | each isNumber]

In Pharo and my library, it straightforwardly answers #[4].
In Squeak, it raises an exception.

So that's sets where the current Squeak definition can give you
trouble, and ByteArrays, and we are not done yet!  Pretty much
anything other than an Array or an OrderedCollection is going to
get you in trouble in Squeak.  Just think of the fun you can
have with SortedCollection.  Ooh, the list goes on and on.

So, the Squeak definition
* does not improve readability.
  In fact, it REDUCES readability because the human reader stops
  to ask "why is this portmanteau method used rather than the
  obvious code" and several minutes later discovers that there
  is NO reason.
* is useless with most collection classes.
* does nothing to improve performance but just adds overhead.

Are we done yet?



On Tue, 10 Sep 2019 at 01:27, David T. Lewis  wrote:

> On Mon, Sep 09, 2019 at 05:46:48PM +1200, Richard O'Keefe wrote:
> >
> > (3) Oddly enough, the reason that #collect:thenDo: exists in my
> > library is that I copied it from Squeak, at a time when it had
> > the same definition as Pharo and ST/X.  Had I known of the change
> > in Squeak I would have bitterly opposed it.  The comment in the
> > current Squeak code, that it is for readability, is 100% the
> > reverse of the truth.  Using the version with parentheses is WAY
> > clearer than using the portmanteau method.  Sigh.  I see they
> > broke #collect:thenSelect: in the same way.
> >
>
> In Squeak, collect:thenDo: is implemented only in Collection.
> The method stamp is dgd 9/13/2004 23:42, which hardly qualifies as
> a recent change. And the method stamp for collect:thenSelect: is
> sma 5/12/2000.
>
> Dave
>
>
>


Re: [Pharo-users] My Pharo Wiki

2019-09-09 Thread Julien
Hello Sean,

Nice work. :-)

Do you know about pharo-open-documentation/pharo-wiki [1] ?

With Cyril and Oleks, we started it to collect code snippets.

Now that it gows bigger and people start to contribute, we try to build a real 
wiki to document obscure features of Pharo.

Tell us if you want to contribute, we would be happy of any help! :-)

Cheers,

Julien

Links:
[1]: https://github.com/pharo-open-documentation/pharo-wiki 


---
Julien Delplanque
Doctorant à l’Université de Lille
http://juliendelplanque.be/phd.html
Equipe Rmod, Inria
Bâtiment B 40, Avenue Halley 59650 Villeneuve d'Ascq
Numéro de téléphone: +333 59 35 86 40

> Le 9 sept. 2019 à 20:18, Sean P. DeNigris  a écrit :
> 
> I've been collecting Pharo tidbits that I found interesting for quite a
> while. I was aggregating everything today and realized that it had grown
> into a small "cookbook" which has some useful information not otherwise
> easily available. I share it in case it is of help:
> 
> https://github.com/seandenigris/pharo/wiki
> 
> NB it was written for my personal use so it may be rough around the edges.
> Feel free to ask questions if I can clarify anything.
> 
> 
> 
> -
> Cheers,
> Sean
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
> 



[Pharo-users] My Pharo Wiki

2019-09-09 Thread Sean P. DeNigris
I've been collecting Pharo tidbits that I found interesting for quite a
while. I was aggregating everything today and realized that it had grown
into a small "cookbook" which has some useful information not otherwise
easily available. I share it in case it is of help:

https://github.com/seandenigris/pharo/wiki

NB it was written for my personal use so it may be rough around the edges.
Feel free to ask questions if I can clarify anything.



-
Cheers,
Sean
--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html



Re: [Pharo-users] Set >> collect:thenDo:

2019-09-09 Thread Steffen Märcker

I think this thread indicates that the selector #collect:thenDo: may
indeed cause some missunderstanding given standard semantics of #collect:.
Is there any reason not to use a different one, such as #map:thenDo:, to
make the difference clearer?

A nice side effect could be a new automatic refactoring rule that
consolidates chained #collect: and #do: sends into a faster
#collect:thenDo: send without breaking existing code.

Am .09.2019, 07:46 Uhr, schrieb Richard O'Keefe :


(1) If you want (aSet collect: collectBlock) do: doBlock
you can write exactly that.  Nothing stops you, and it will
be as clear and reliable as any use of Set>>collect:, which
is to say NOT VERY CLEAR OR RELIABLE AT ALL.

(2) #collect:then{Do:Select:Reject:} had no other purpose than
to avoid creating an intermediate and otherwise useless
collection.  If you are not trying to involve an intermediate
set then it just plain wrong to use #collect:thenDo:.

(3) Oddly enough, the reason that #collect:thenDo: exists in my
library is that I copied it from Squeak, at a time when it had
the same definition as Pharo and ST/X.  Had I known of the change
in Squeak I would have bitterly opposed it.  The comment in the
current Squeak code, that it is for readability, is 100% the
reverse of the truth.  Using the version with parentheses is WAY
clearer than using the portmanteau method.  Sigh.  I see they
broke #collect:thenSelect: in the same way.

(4) Let me offer you another member of the #collect:then* family.

Collection
  collect: collectBlock thenInject: initial into: injectBlock
|r|
r := initial.
self do: [:each |
  r := injectBlock value: r value: (collectBlock value: each)].
^r

#(now is the hour for us to say goodbye) asSet
  collect: [:each | each size]
  thenInject: 0 into: [:acc :each | acc + each]
 => 29
(#(now is the hour for us to say goodbye) asSet
  collect: [:each | each size])
  inject: 0 into: [:acc :each | acc + each]
 => 16

   That is, it would be WRONG to implement #collect:thenInject:into:
   as #collect: followed by #inject:into:.  The point is NOT to
   coalesce things that the receiver might (in general, incorrectly)
   regard as equal.

(5) The bottom line is that if #collect:thenDo: and its relatives did
not have their present semantics in Pharo (and ST/X), they would
need to be reinvented, with names that were not as clear.

(1) Just to repeat for emphasis, if you *want* (_ collect: _) do: _
then that is exactly what you should write.  There is no
excuse for using #collect:thenDo: in that case.  It is NOT
clearer to do so.  And you should imagine me jumping up and
down screaming that sending #collect: to a set is a bad code
smell which demands very explicit documentation as to why you
(for example) want a Set to answer a Set but an IdentitySet
to also answer a Set, not the expected IdentitySet.  (I have
been bitten by that more than once.)



On Mon, 9 Sep 2019 at 01:33, Herby Vojčík  wrote:


On 8. 9. 2019 14:28, Peter Kenny wrote:
> Two comments:
> First, the method comment for Collection>>collect:thenDo: is "Utility
method
> to improve readability", which is exactly the same as for
> collect:thenSelect: and collect:thenReject:. This suggests that the
> *intention* of the method is not to introduce new behaviour, but
simply
to
> provide a shorthand for the version with parentheses. For other kinds
of

I had that same impression.

> collection this is true; just the deduping makes Set different. If we
want

I would be more defensive here and say that generic collection should
have (collect:)do: implementation and only sequenceable collections have
the optimized one (if it indeed is the case that it is a shotrhand for
parenthesized one).

> the different behaviour, this should be indicated by method name and
> comment.
> Second, if we remove asSet from the second snippet, the output is
exactly
> the same. It will be the same as long as the original collection has
no
> duplicates. Somehow the effect is to ignore the asSet. It just smells
wrong.
>
> Peter Kenny

Herby

> Kasper Osterbye wrote
>> The first version:
>>
>> (#(1 2 3) asSet collect: #odd)
>> do: [ :each | Transcript show: each; cr ]
>>
>> is rather straight forward I believe, as collect: and do: has been
around
>> forever (relatively speaking).
>>
>>
>> #(1 2 3) asSet collect: #odd
>> thenDo: [ :each | Transcript show: each; cr ]
>>
>>
>> On 8 September 2019 at 09.13.36, Richard Sargent (
>
>> richard.sargent@
>
>> ) wrote:
>>
>>   I am skeptical of one that relies on a specific implementation
rather
>> than
>> a specific definition.
>>
>> I share your feeling. I am not sure where such a definition would
come
>> from. In Squeak it is defined as:
>>
>> collect: collectBlock thenDo: doBlock
>>
>> ^ (self collect: collectBlock) do: doBlock
>>
>> In pharo as:
>>
>> collect: collectBlock thenDo: 

Re: [Pharo-users] Set >> collect:thenDo:

2019-09-09 Thread David T. Lewis
On Mon, Sep 09, 2019 at 05:46:48PM +1200, Richard O'Keefe wrote:
> 
> (3) Oddly enough, the reason that #collect:thenDo: exists in my
> library is that I copied it from Squeak, at a time when it had
> the same definition as Pharo and ST/X.  Had I known of the change
> in Squeak I would have bitterly opposed it.  The comment in the
> current Squeak code, that it is for readability, is 100% the
> reverse of the truth.  Using the version with parentheses is WAY
> clearer than using the portmanteau method.  Sigh.  I see they
> broke #collect:thenSelect: in the same way.
>

In Squeak, collect:thenDo: is implemented only in Collection.
The method stamp is dgd 9/13/2004 23:42, which hardly qualifies as
a recent change. And the method stamp for collect:thenSelect: is
sma 5/12/2000.

Dave
 



Re: [Pharo-users] uFFI Structure Problem

2019-09-09 Thread Georg Hagn
Thank you Esteban for your fast answer.

1) NULL Pointer assignment:
I have implemented your advise, and changed the attribute "abrufCode"
to "ExternalAddress null";
>> fieldDesc #(myStruct uint32 version;  ...  void * abrufCode; )
The Structure has a NULL pointer assigned!? (see Inspector on MyStruct
"MyStruct (
version: 2
zertifikatHandle: (void*)@ 16r7F840001
pin: (char*)@ 16r7F84FB7FE5A0
abrufCode: (void*)@ 16r
)"

But the problem is the same. I get the error: "attribute abrufCode
must have the value NULL." Any ideas?

2) coercing problem:
In my various tries I changed the whole structure to ExternalAddress
null. (In some circumstances I have to set the whole Structure to
NULL)
Now I got an coercing error. I think, because ExternalAddress is not a
FFIExternalStructure.
"
^ self ffiCall: #(int BearbeiteVorgang(String daten, String version,
int flags,  ExternalAddress * druck, MyStruct * crypto, TransferHandle
* transfer, RueckgabeHandle * rueckgabe, RueckgabeHandle *
serverantwort)).
"
Is it possible, NOT to decide between (here 4: druck and crypto can be
either Structures or NULL) ffi-calls?

Thank you, Georg








Am Do., 5. Sept. 2019 um 16:30 Uhr schrieb Esteban Lorenzano
:
>
>
>
> On 5 Sep 2019, at 17:41, Georg Hagn  wrote:
>
> I have to implemet following external structure (extrakt from the
> german api Doku):
>
> typedef struct {
> /**@brief MUST be always 2. */
> uint32_t version;
>
> /** @brief Pointer to KeyStore -- Verweis auf den KeyStore, see
> EricGetHandleToCertificate(). */
> EricZertifikatHandle zertifikatHandle;
>
> /** @brief PIN für den KeyStore.*/
> const char *pin;
>
> /**
>  * @brief MUST be NULL in my context
>   Dieser muss ...
>   In allen anderen Fällen muss hier NULL übergeben
> werden. Der Parameter abrufCode
>   besteht aus 2 x 5 Zeichen, die mit "-" verbunden sind.
>   Beispiel: "K6FG5-RS32P"
>  */
> const char *abrufCode;
>
> } eric_verschluesselungs_parameter_t;
>
> My Problem is, that i have to assign a NULL - value to the attribute 
> abrufCode.
> I have tried varies possibilities but I get always the error, that the
> attribute abrufCode must have the value NULL.
>
> " Extract from log-file:
> 019-09-05 17:08:52,257709[0x7fe036a2f050] ERROR: Für die
> übermittelte Datenart ist die Angabe eines Abrufcodes nicht zulässig,
> daher muss für den Abrufcode der Wert NULL übergeben werden.
> 610001029"
>
> How do I assign a NULL value to an attribute in a FFIExternalStructure?
>
>
> The problem is not that is an structure but that is a char *, which is 
> converted to a String in Pharo.
> Ideally, a nil should be mapped to NULL in this cases, but this is not 
> working (never implemented).
>
> Easiest workaround, just map abrufCode to void * instead char * (pointers are 
> always same size).
>
> So you can have:
>
> myStryct abrufCode: ExternalAddress null.
>
> But of course, that will change the way you put the value there when *it is 
> not* a NULL:
>
> myStryct abrufCode: ‘hello’ utf8Encoded copyWith 0.
>
> (The copyWith: 0 is to ensure the void * will receive something with proper 
> \0 finalisation)
>
> Esteban
>
>
> Following my last attempt (extracted from the Pharo Booklet Colletion
> "Calling Foreign Functions with Pharo May 31,2018")
> I assign values not directly with the generated attributes but with
> "api???" attributes.
>
> FFIExternalStructure subclass: #ERiCVerschluesselungsParameter
>instanceVariableNames: ''
>classVariableNames: 'OFFSET_ABRUFCODE OFFSET_PIN OFFSET_VERSION
> OFFSET_ZERTIFIKATHANDLE'
>package: 'Bajoras-ERiC'!
>
>
> ERiCVerschluesselungsParameter class >> fieldsDesc [
>
>"ERiCVerschluesselungsParameter rebuildFieldAccessors"
>
>^ #(
>uint32 version;
>ERiCZertifikatHandle * zertifikatHandle;
>char * pin;
>char * abrufCode;
>)
> ]
>
> ERiCVerschluesselungsParameter >> initialize [
>
>self
>apiVersion: 2;
>apiAbrufCode: nil;
>apiPin: 'mySecret'.
> ]
>
> ERiCVerschluesselungsParameter >> accessorMethods for: pin, version,
> abrufCode, zertifikatHandle ("This method were automatically
> generated")
>
> ERiCVerschluesselungsParameter >> apiAbrufCode: aCode [
>
>| codeSize anAbrufCode |
>
>codeSize := 11.
>anAbrufCode := FFIExternalArray externalNewType: 'char' size: codeSize.
>1 to: codeSize do: [ :idx | anAbrufCode at: idx put: Character null ] .
>
>aCode ifNotNil: [
>aCode doWithIndex: [ :char :i | anAbrufCode at: i put: char ].
>].
>
>self abrufCode: anAbrufCode.
>
> ]
>
> ERiCVerschluesselungsParameter >> apiPin: aPin [
>
>| newPin |
>
>newPin := FFIExternalArray externalNewType: 'char' size: aPin size.
>aPin doWithIndex: [ :char :i | newPin at: i put: char ].
>
>self pin: newPin.
> ]
>
>
> ERiCVerschluesselungsParameter >> apiVersion: aVersion [
>
>| cryptoVersion |
>
>cryptoVersion := 2.
>