#(foo bar baz) min

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

#(foo bar baz) min

Herby Vojčík
Hi all!

Somehow intuitively I presume the subject line to return #bar, but it
fails with ByteString not knowing min:, in Pharo 6.1.

Is it a bug, bug fixed in Pharo 7, or a feature?

Herby

Reply | Threaded
Open this post in threaded view
|

Re: #(foo bar baz) min

Sven Van Caekenberghe-2


> On 20 Apr 2018, at 20:42, Herbert Vojčík <[hidden email]> wrote:
>
> Hi all!
>
> Somehow intuitively I presume the subject line to return #bar, but it fails with ByteString not knowing min:, in Pharo 6.1.
>
> Is it a bug, bug fixed in Pharo 7, or a feature?
>
> Herby

I would say that should work.
Strings and Symbols are comparable and sortable.
Furthermore #min: & #max: are part of TComparable.

Sven
Reply | Threaded
Open this post in threaded view
|

Re: #(foo bar baz) min

Richard O'Keefe
#('a' 'b' 'c') min
also fails on the grounds that ByteStrings don't understand #min:.
What's worse is that ByteString and ByteSymbol *do* have #max:,
but it's something quite different (and arguably broken).

max: aBlock
    | max |
    self ifEmpty: [ ^ nil ].
    max := aBlock value: self first.
    self
        allButFirstDo:
            [ :each |
            | value |
            value := aBlock value: each.
            max := max max: value ].
    ^ max

It would be better if the TComparable #min: and #max:
were available and the current #max: renamed to something else.
I have this in an extension to GNU Smalltalk:

Collection extend [
    collect: collectBlock thenFold: foldBlock [
        |started result|
        started := result := nil.
        self do: [:each | |v|
            v := collectBlock value: each.
            result := started ifNil: [started := self. v]
                           ifNotNil: [foldBlock value: result value: v]].
        ^started ifNil: [SystemExceptions.EmptyCollection signalOn: self]
              ifNotNil: [result]
    ]

    collectThenMin: collectBlock [
        ^self collect: collectBlock thenFold: [:acc :y | acc min: y]
    ]
    min [
        ^self collectThenMin: [:each | each]
    ]

    collectThenMax: collectBlock [
        ^self collect: collectBlock thenFold: [:acc :y | acc max: y]
    ]
    max [
        ^self collectThenMax: [:each | each]
    ]
]

CharacterArray extend [
    max: other [
      ^self < other ifTrue: [other] ifFalse: [self]
    ]

    min: other [
      ^self < other ifTrue: [self] ifFalse: [other]
    ]
]

Reply | Threaded
Open this post in threaded view
|

Re: #(foo bar baz) min

Stephane Ducasse-3
Hi richard

do you have some tests around?

Stef

On Sat, Apr 21, 2018 at 3:07 PM, Richard O'Keefe <[hidden email]> wrote:

> #('a' 'b' 'c') min
> also fails on the grounds that ByteStrings don't understand #min:.
> What's worse is that ByteString and ByteSymbol *do* have #max:,
> but it's something quite different (and arguably broken).
>
> max: aBlock
>     | max |
>     self ifEmpty: [ ^ nil ].
>     max := aBlock value: self first.
>     self
>         allButFirstDo:
>             [ :each |
>             | value |
>             value := aBlock value: each.
>             max := max max: value ].
>     ^ max
>
> It would be better if the TComparable #min: and #max:
> were available and the current #max: renamed to something else.
> I have this in an extension to GNU Smalltalk:
>
> Collection extend [
>     collect: collectBlock thenFold: foldBlock [
>         |started result|
>         started := result := nil.
>         self do: [:each | |v|
>             v := collectBlock value: each.
>             result := started ifNil: [started := self. v]
>                            ifNotNil: [foldBlock value: result value: v]].
>         ^started ifNil: [SystemExceptions.EmptyCollection signalOn: self]
>               ifNotNil: [result]
>     ]
>
>     collectThenMin: collectBlock [
>         ^self collect: collectBlock thenFold: [:acc :y | acc min: y]
>     ]
>     min [
>         ^self collectThenMin: [:each | each]
>     ]
>
>     collectThenMax: collectBlock [
>         ^self collect: collectBlock thenFold: [:acc :y | acc max: y]
>     ]
>     max [
>         ^self collectThenMax: [:each | each]
>     ]
> ]
>
> CharacterArray extend [
>     max: other [
>       ^self < other ifTrue: [other] ifFalse: [self]
>     ]
>
>     min: other [
>       ^self < other ifTrue: [self] ifFalse: [other]
>     ]
> ]
>

Reply | Threaded
Open this post in threaded view
|

Re: #(foo bar baz) min

Herby Vojčík
In reply to this post by Richard O'Keefe
Note: no need for #collect:thenFold: family, one can implement min as

   min
     ^ self detectMin: [ :x | x ]

if you want to reuse existing one.

But actually, the issue is, min: and max: are not there (correctly) for
strings.

Herby

Richard O'Keefe wrote:

> #('a' 'b' 'c') min
> also fails on the grounds that ByteStrings don't understand #min:.
> What's worse is that ByteString and ByteSymbol *do* have #max:,
> but it's something quite different (and arguably broken).
>
> max: aBlock
>      | max |
>      self ifEmpty: [ ^ nil ].
>      max := aBlock value: self first.
>      self
>          allButFirstDo:
>              [ :each |
>              | value |
>              value := aBlock value: each.
>              max := max max: value ].
>      ^ max
>
> It would be better if the TComparable #min: and #max:
> were available and the current #max: renamed to something else.
> I have this in an extension to GNU Smalltalk:
>
> Collection extend [
>      collect: collectBlock thenFold: foldBlock [
>          |started result|
>          started := result := nil.
>          self do: [:each | |v|
>              v := collectBlock value: each.
>              result := started ifNil: [started := self. v]
>                             ifNotNil: [foldBlock value: result value: v]].
>          ^started ifNil: [SystemExceptions.EmptyCollection signalOn: self]
>                ifNotNil: [result]
>      ]
>
>      collectThenMin: collectBlock [
>          ^self collect: collectBlock thenFold: [:acc :y | acc min: y]
>      ]
>      min [
>          ^self collectThenMin: [:each | each]
>      ]
>
>      collectThenMax: collectBlock [
>          ^self collect: collectBlock thenFold: [:acc :y | acc max: y]
>      ]
>      max [
>          ^self collectThenMax: [:each | each]
>      ]
> ]
>
> CharacterArray extend [
>      max: other [
>        ^self < other ifTrue: [other] ifFalse: [self]
>      ]
>
>      min: other [
>        ^self < other ifTrue: [self] ifFalse: [other]
>      ]
> ]
>

Reply | Threaded
Open this post in threaded view
|

Re: #(foo bar baz) min

Sean P. DeNigris
Administrator
Herby Vojčík wrote
> … detectMin: [ :x | x ]

Or `detectMin: #yourself` if you prefer



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

Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: #(foo bar baz) min

Richard O'Keefe
In reply to this post by Herby Vojčík
I did say that the code I posted was a *GNU Smalltalk* extension.
The version of GNU Smalltalk on my machine doesn't have #detectMin:
or #detectMax:.

As for test cases:

    self assert: #(3 1 4 2) min equals: 1.
    self assert: #(3 1 4 2) max equals: 4.
    self assert: #('C' 'A' 'D' 'B') min equals: 'A'.
    self assert: #('C' 'A' 'D' 'B') max equals: 'D'.
    self assert: #(c a d b) min equals: #a.
    self assert: #(c a d b) max equals: #d.

On 22 April 2018 at 02:33, Herbert Vojčík <[hidden email]> wrote:
Note: no need for #collect:thenFold: family, one can implement min as

  min
    ^ self detectMin: [ :x | x ]

if you want to reuse existing one.

But actually, the issue is, min: and max: are not there (correctly) for strings.

Herby


Richard O'Keefe wrote:
#('a' 'b' 'c') min
also fails on the grounds that ByteStrings don't understand #min:.
What's worse is that ByteString and ByteSymbol *do* have #max:,
but it's something quite different (and arguably broken).

max: aBlock
     | max |
     self ifEmpty: [ ^ nil ].
     max := aBlock value: self first.
     self
         allButFirstDo:
             [ :each |
             | value |
             value := aBlock value: each.
             max := max max: value ].
     ^ max

It would be better if the TComparable #min: and #max:
were available and the current #max: renamed to something else.
I have this in an extension to GNU Smalltalk:

Collection extend [
     collect: collectBlock thenFold: foldBlock [
         |started result|
         started := result := nil.
         self do: [:each | |v|
             v := collectBlock value: each.
             result := started ifNil: [started := self. v]
                            ifNotNil: [foldBlock value: result value: v]].
         ^started ifNil: [SystemExceptions.EmptyCollection signalOn: self]
               ifNotNil: [result]
     ]

     collectThenMin: collectBlock [
         ^self collect: collectBlock thenFold: [:acc :y | acc min: y]
     ]
     min [
         ^self collectThenMin: [:each | each]
     ]

     collectThenMax: collectBlock [
         ^self collect: collectBlock thenFold: [:acc :y | acc max: y]
     ]
     max [
         ^self collectThenMax: [:each | each]
     ]
]

CharacterArray extend [
     max: other [
       ^self < other ifTrue: [other] ifFalse: [self]
     ]

     min: other [
       ^self < other ifTrue: [self] ifFalse: [other]
     ]
]