Pharo-users
By thread
pharo-users@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- August
- 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
- 7 participants
- 50354 messages
Re: [Pharo-users] Porting Transducers to Pharo
by Damien Pollet
I got stumped / life moved onâ¦
>From the top of my head, my port was working for the most part (the tests
rely on a mocking library that should be ported as well; translating to
either BabyMock2 or Mocketry seems possible on the surface but there is
some impedance mismatch there between the features and DSLs of those libs)
I had to do a fileout and fiddle in VW to do it in the squeak format, then
had to grep/sed/hand-rewrite some non-portable stuff (replacing class
references with corresponding ones, removing namespacesâ¦).
For FileTree, it was conforming to a different version of Cypress than
STIG; I started exploring how to fix that but lost interest.
On 31 May 2017 at 16:29, Steffen Märcker <merkste(a)web.de> wrote:
> Hello Damien,
>
> I remember very well. How far did you get? Did you kick of a discussion on
> one of the Pharo lists? And did FileTree become a convenient way to
> exchange code between VW and Pharo?
>
> Best,
> Steffen
>
>
>
> Am .05.2017, 16:16 Uhr, schrieb Damien Pollet <
> damien.pollet+pharo(a)gmail.com>:
>
> As you know I experimented with that a while ago. My code is at
>> http://smalltalkhub.com/#!/~cdlm/Experiments/source
>>
>> On 31 May 2017 at 15:00, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>>
>>
>>> > On 31 May 2017, at 14:23, Steffen Märcker <merkste(a)web.de> wrote:
>>> >
>>> > Hi,
>>> >
>>> > I am the developer of the library 'Transducers' for VisualWorks. It was
>>> formerly known as 'Reducers', but this name was a poor choice. I'd like
>>> to
>>> port it to Pharo, if there is any interest on your side. I hope to learn
>>> more about Pharo in this process, since I am mainly a VW guy. And most
>>> likely, I will come up with a bunch of questions. :-)
>>> >
>>> > Meanwhile, I'll cross-post the introduction from VWnc below. I'd be
>>> very
>>> happy to hear your optinions, questions and I hope we can start a
>>> fruitful
>>> discussion - even if there is not Pharo port yet.
>>> >
>>> > Best, Steffen
>>>
>>> Hi Steffen,
>>>
>>> Looks like very interesting stuff. Would make an nice library/framework
>>> for Pharo.
>>>
>>> Sven
>>>
>>> > Transducers are building blocks that encapsulate how to process
>>> elements
>>> > of a data sequence independently of the underlying input and output
>>> source.
>>> >
>>> >
>>> >
>>> > # Overview
>>> >
>>> > ## Encapsulate
>>> > Implementations of enumeration methods, such as #collect:, have the
>>> logic
>>> > how to process a single element in common.
>>> > However, that logic is reimplemented each and every time. Transducers
>>> make
>>> > it explicit and facilitate re-use and coherent behavior.
>>> > For example:
>>> > - #collect: requires mapping: (aBlock1 map)
>>> > - #select: requires filtering: (aBlock2 filter)
>>> >
>>> >
>>> > ## Compose
>>> > In practice, algorithms often require multiple processing steps, e.g.,
>>> > mapping only a filtered set of elements.
>>> > Transducers are inherently composable, and hereby, allow to make the
>>> > combination of steps explicit.
>>> > Since transducers do not build intermediate collections, their
>>> composition
>>> > is memory-efficient.
>>> > For example:
>>> > - (aBlock1 filter) * (aBlock2 map) "(1.) filter and (2.) map
>>> elements"
>>> >
>>> >
>>> > ## Re-Use
>>> > Transducers are decoupled from the input and output sources, and hence,
>>> > they can be reused in different contexts.
>>> > For example:
>>> > - enumeration of collections
>>> > - processing of streams
>>> > - communicating via channels
>>> >
>>> >
>>> >
>>> > # Usage by Example
>>> >
>>> > We build a coin flipping experiment and count the occurrence of heads
>>> and
>>> > tails.
>>> >
>>> > First, we associate random numbers with the sides of a coin.
>>> >
>>> > scale := [:x | (x * 2 + 1) floor] map.
>>> > sides := #(heads tails) replace.
>>> >
>>> > Scale is a transducer that maps numbers x between 0 and 1 to 1 and 2.
>>> > Sides is a transducer that replaces the numbers with heads an tails by
>>> > lookup in an array.
>>> > Next, we choose a number of samples.
>>> >
>>> > count := 1000 take.
>>> >
>>> > Count is a transducer that takes 1000 elements from a source.
>>> > We keep track of the occurrences of heads an tails using a bag.
>>> >
>>> > collect := [:bag :c | bag add: c; yourself].
>>> >
>>> > Collect is binary block (reducing function) that collects events in a
>>> bag.
>>> > We assemble the experiment by transforming the block using the
>>> transducers.
>>> >
>>> > experiment := (scale * sides * count) transform: collect.
>>> >
>>> > From left to right we see the steps involved: scale, sides, count and
>>> > collect.
>>> > Transforming assembles these steps into a binary block (reducing
>>> function)
>>> > we can use to run the experiment.
>>> >
>>> > samples := Random new
>>> > reduce: experiment
>>> > init: Bag new.
>>> >
>>> > Here, we use #reduce:init:, which is mostly similar to #inject:into:.
>>> > To execute a transformation and a reduction together, we can use
>>> > #transduce:reduce:init:.
>>> >
>>> > samples := Random new
>>> > transduce: scale * sides * count
>>> > reduce: collect
>>> > init: Bag new.
>>> >
>>> > We can also express the experiment as data-flow using #<~.
>>> > This enables us to build objects that can be re-used in other
>>> experiments.
>>> >
>>> > coin := sides <~ scale <~ Random new.
>>> > flip := Bag <~ count.
>>> >
>>> > Coin is an eduction, i.e., it binds transducers to a source and
>>> > understands #reduce:init: among others.
>>> > Flip is a transformed reduction, i.e., it binds transducers to a
>>> reducing
>>> > function and an initial value.
>>> > By sending #<~, we draw further samples from flipping the coin.
>>> >
>>> > samples := flip <~ coin.
>>> >
>>> > This yields a new Bag with another 1000 samples.
>>> >
>>> >
>>> >
>>> > # Basic Concepts
>>> >
>>> > ## Reducing Functions
>>> >
>>> > A reducing function represents a single step in processing a data
>>> sequence.
>>> > It takes an accumulated result and a value, and returns a new
>>> accumulated
>>> > result.
>>> > For example:
>>> >
>>> > collect := [:col :e | col add: e; yourself].
>>> > sum := #+.
>>> >
>>> > A reducing function can also be ternary, i.e., it takes an accumulated
>>> > result, a key and a value.
>>> > For example:
>>> >
>>> > collect := [:dic :k :v | dict at: k put: v; yourself].
>>> >
>>> > Reducing functions may be equipped with an optional completing action.
>>> > After finishing processing, it is invoked exactly once, e.g., to free
>>> > resources.
>>> >
>>> > stream := [:str :e | str nextPut: each; yourself] completing:
>>> #close.
>>> > absSum := #+ completing: #abs
>>> >
>>> > A reducing function can end processing early by signaling Reduced with
>>> a
>>> > result.
>>> > This mechanism also enables the treatment of infinite sources.
>>> >
>>> > nonNil := [:res :e | e ifNil: [Reduced signalWith: res] ifFalse:
>>> [res]].
>>> >
>>> > The primary approach to process a data sequence is the reducing
>>> protocol
>>> > with the messages #reduce:init: and #transduce:reduce:init: if
>>> transducers
>>> > are involved.
>>> > The behavior is similar to #inject:into: but in addition it takes care
>>> of:
>>> > - handling binary and ternary reducing functions,
>>> > - invoking the completing action after finishing, and
>>> > - stopping the reduction if Reduced is signaled.
>>> > The message #transduce:reduce:init: just combines the transformation
>>> and
>>> > the reducing step.
>>> >
>>> > However, as reducing functions are step-wise in nature, an application
>>> may
>>> > choose other means to process its data.
>>> >
>>> >
>>> > ## Reducibles
>>> >
>>> > A data source is called reducible if it implements the reducing
>>> protocol.
>>> > Default implementations are provided for collections and streams.
>>> > Additionally, blocks without an argument are reducible, too.
>>> > This allows to adapt to custom data sources without additional effort.
>>> > For example:
>>> >
>>> > "XStreams adaptor"
>>> > xstream := filename reading.
>>> > reducible := [[xstream get] on: Incomplete do: [Reduced signal]].
>>> >
>>> > "natural numbers"
>>> > n := 0.
>>> > reducible := [n := n+1].
>>> >
>>> >
>>> > ## Transducers
>>> >
>>> > A transducer is an object that transforms a reducing function into
>>> another.
>>> > Transducers encapsulate common steps in processing data sequences, such
>>> as
>>> > map, filter, concatenate, and flatten.
>>> > A transducer transforms a reducing function into another via
>>> #transform:
>>> > in order to add those steps.
>>> > They can be composed using #* which yields a new transducer that does
>>> both
>>> > transformations.
>>> > Most transducers require an argument, typically blocks, symbols or
>>> numbers:
>>> >
>>> > square := Map function: #squared.
>>> > take := Take number: 1000.
>>> >
>>> > To facilitate compact notation, the argument types implement
>>> corresponding
>>> > methods:
>>> >
>>> > squareAndTake := #squared map * 1000 take.
>>> >
>>> > Transducers requiring no argument are singletons and can be accessed by
>>> > their class name.
>>> >
>>> > flattenAndDedupe := Flatten * Dedupe.
>>> >
>>> >
>>> >
>>> > # Advanced Concepts
>>> >
>>> > ## Data flows
>>> >
>>> > Processing a sequence of data can often be regarded as a data flow.
>>> > The operator #<~ allows define a flow from a data source through
>>> > processing steps to a drain.
>>> > For example:
>>> >
>>> > squares := Set <~ 1000 take <~ #squared map <~ (1 to: 1000).
>>> > fileOut writeStream <~ #isSeparator filter <~ fileIn readStream.
>>> >
>>> > In both examples #<~ is only used to set up the data flow using
>>> reducing
>>> > functions and transducers.
>>> > In contrast to streams, transducers are completely independent from
>>> input
>>> > and output sources.
>>> > Hence, we have a clear separation of reading data, writing data and
>>> > processing elements.
>>> > - Sources know how to iterate over data with a reducing function, e.g.,
>>> > via #reduce:init:.
>>> > - Drains know how to collect data using a reducing function.
>>> > - Transducers know how to process single elements.
>>> >
>>> >
>>> > ## Reductions
>>> >
>>> > A reduction binds an initial value or a block yielding an initial value
>>> to
>>> > a reducing function.
>>> > The idea is to define a ready-to-use process that can be applied in
>>> > different contexts.
>>> > Reducibles handle reductions via #reduce: and #transduce:reduce:
>>> > For example:
>>> >
>>> > sum := #+ init: 0.
>>> > sum1 := #(1 1 1) reduce: sum.
>>> > sum2 := (1 to: 1000) transduce: #odd filter reduce: sum.
>>> >
>>> > asSet := [:set :e | set add: e; yourself] initializer: [Set new].
>>> > set1 := #(1 1 1) reduce: asSet.
>>> > set2 := #(1 to: 1000) transduce: #odd filter reduce: asSet.
>>> >
>>> > By combining a transducer with a reduction, a process can be further
>>> > modified.
>>> >
>>> > sumOdds := sum <~ #odd filter
>>> > setOdds := asSet <~ #odd filter
>>> >
>>> >
>>> > ## Eductions
>>> >
>>> > An eduction combines a reducible data sources with a transducer.
>>> > The idea is to define a transformed (virtual) data source that needs
>>> not
>>> > to be stored in memory.
>>> >
>>> > odds1 := #odd filter <~ #(1 2 3) readStream.
>>> > odds2 := #odd filter <~ (1 to 1000).
>>> >
>>> > Depending on the underlying source, eductions can be processed once
>>> > (streams, e.g., odds1) or multiple times (collections, e.g., odds2).
>>> > Since no intermediate data is stored, transducers actions are lazy,
>>> i.e.,
>>> > they are invoked each time the eduction is processed.
>>> >
>>> >
>>> >
>>> > # Origins
>>> >
>>> > Transducers is based on the same-named Clojure library and its ideas.
>>> > Please see:
>>> > http://clojure.org/transducers
>>> >
>>>
>>>
>>>
>
May 31, 2017
ANTLR4 to SmaCC
by Henrique Rocha
Hello,
I was trying to convert a ANTLR4 grammar specification to SmaCC. After many
unsuccessful tries that made me question my sanity I wondered: maybe someone
has a solution. Grammar conversion is something that can be automated.
My question is if anyone has done something to convert an ANTLR4 grammar to
a SmaCC grammar?
Thanks and farewell,
- Henrique
--
View this message in context: http://forum.world.st/ANTLR4-to-SmaCC-tp4948738.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
May 31, 2017
Re: [Pharo-users] Morphic or forking bug?
by Denis Kudriashov
2017-05-31 16:24 GMT+02:00 horrido <horrido.hobbies(a)gmail.com>:
> Oh, I forgot to mention, the crash dump says I got a segmentation fault.
This is of course needs attention. What pharo you are using? what VM,
images, OS?
May 31, 2017
Re: [Pharo-users] Morphic or forking bug?
by Denis Kudriashov
Hi Horrido.
Morphic is not thread safe library. Users should not update morphs state
directly from background processes. Use #defer: message to update morphs in
such cases.
Try following loop:
[ [ true ] whileTrue: [ UIManager default defer: [ a contents: 0
asString]. delay wait ] fork
2017-05-31 16:23 GMT+02:00 horrido <horrido.hobbies(a)gmail.com>:
> I have a puzzling bug. I've narrowed the scenario down to this code:
>
> Cranky»initA
> a := ((StringMorph contents: '####') color: Color white) position: (0@0
> ).
> m addMorph: a
>
> Cranky»initialize
> f := Form fromFileNamed: 'hot_air_balloon_mysticmorning.jpg'.
> m := ImageMorph new.
> m form: f.
> self initA.
> m openInWindowLabeled: 'Cranky'.
> delay := (Delay forSeconds: 5).
> [ [ true ] whileTrue: [ a contents: 0 asString. delay wait ] fork
>
> I can run this application for hours and hours with no problem. However, if
> I run it for a while and then close the application and then save/exit the
> image, the next time I start the image, there is some likelihood it will
> crash dump. The probability is something like 5-10%.
>
> Interestingly, if I remove the statement...
>
> a contents: 0 asString.
>
> from the infinite loop, I've not been able to replicate the crash. Is there
> something wrong with the way I'm updating the contents of the StringMorph?
>
>
>
> --
> View this message in context: http://forum.world.st/Morphic-
> or-forking-bug-tp4948727.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>
>
May 31, 2017
Re: [Pharo-users] Porting Transducers to Pharo
by Esteban A. Maringolo
FileTree is the Pharo implementation of the Cypress format for
packages, STIG is the implementation of Cypress for VW.
The latest changes are available in
<https://github.com/martinmcclure/STIG>, but it doesn't work out of
the box.
I'm interested in having a way to share code back and forth between
Pharo and VW, currently I'm moving code from Pharo to VW, but using a
modified version of the exporter available in Roassal, and the process
is cumbersome.
Regards!
Esteban A. Maringolo
2017-05-31 11:32 GMT-03:00 Steffen Märcker <merkste(a)web.de>:
> Thanks for the encouraging response! First question: Which is the
> recommended (friction free) way to exchange code between VW and Pharo?
>
> Cheers!
> Steffen
>
>
> Am .05.2017, 16:22 Uhr, schrieb Alexandre Bergel <alexandre.bergel(a)me.com>:
>
>> I second Sven. This is very exciting!
>>
>> Let us know when you have something ready to be tested.
>>
>> Alexandre
>
>
>
>
May 31, 2017
Re: [Pharo-users] Discord server ownership
by Dimitris Chloupis
"Esteban is going to be excited about this :)"
he certainly enjoys the conveniences of his new powers :)
"So you put us all into this gaming chatroom and now you leave. Good move.
;-)
I hope to see you back in the mailing list and chat server (whatever
it is we use at that moment).
Regards!"
hehe good point. I can understand people who did not want to move from
Slack , its the same reason I started with Discord , none of projects I am
interested uses Slack , many of them use Discord. Actually documentation
and wikis are my number 1 choice. Its easy to get lost inside a mailing
lists and online chat content. Even with threads and search facilities
there is so much great content that gets "lost in time like tears in the
rain".
I will be still around and check things out from time to time, I am sure I
will find an excuse to use Pharo again ;)
"Passing the baton at the right time is an important responsibility.
Thanks for your efforts setting up the server in the first place.
cheers -ben"
Thanks ben, I am glad people like it and the transition has been so smooth.
I also like to remind people that Discord has a pretty powerful API so
creating a discord client inside pharo should not be that hard, so if
anyone is interested and needs a couple of starting pointers send me a
message and will send you a couple of links and answer your questions. I
used the the python api but of course there is js api and several other
languages.
May 31, 2017
Re: [Pharo-users] Porting Transducers to Pharo
by Steffen Märcker
Thanks for the encouraging response! First question: Which is the
recommended (friction free) way to exchange code between VW and Pharo?
Cheers!
Steffen
Am .05.2017, 16:22 Uhr, schrieb Alexandre Bergel <alexandre.bergel(a)me.com>:
> I second Sven. This is very exciting!
>
> Let us know when you have something ready to be tested.
>
> Alexandre
May 31, 2017
Re: [Pharo-users] Porting Transducers to Pharo
by Steffen Märcker
Hello Damien,
I remember very well. How far did you get? Did you kick of a discussion on
one of the Pharo lists? And did FileTree become a convenient way to
exchange code between VW and Pharo?
Best,
Steffen
Am .05.2017, 16:16 Uhr, schrieb Damien Pollet
<damien.pollet+pharo(a)gmail.com>:
> As you know I experimented with that a while ago. My code is at
> http://smalltalkhub.com/#!/~cdlm/Experiments/source
>
> On 31 May 2017 at 15:00, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>
>>
>> > On 31 May 2017, at 14:23, Steffen Märcker <merkste(a)web.de> wrote:
>> >
>> > Hi,
>> >
>> > I am the developer of the library 'Transducers' for VisualWorks. It
>> was
>> formerly known as 'Reducers', but this name was a poor choice. I'd like
>> to
>> port it to Pharo, if there is any interest on your side. I hope to learn
>> more about Pharo in this process, since I am mainly a VW guy. And most
>> likely, I will come up with a bunch of questions. :-)
>> >
>> > Meanwhile, I'll cross-post the introduction from VWnc below. I'd be
>> very
>> happy to hear your optinions, questions and I hope we can start a
>> fruitful
>> discussion - even if there is not Pharo port yet.
>> >
>> > Best, Steffen
>>
>> Hi Steffen,
>>
>> Looks like very interesting stuff. Would make an nice library/framework
>> for Pharo.
>>
>> Sven
>>
>> > Transducers are building blocks that encapsulate how to process
>> elements
>> > of a data sequence independently of the underlying input and output
>> source.
>> >
>> >
>> >
>> > # Overview
>> >
>> > ## Encapsulate
>> > Implementations of enumeration methods, such as #collect:, have the
>> logic
>> > how to process a single element in common.
>> > However, that logic is reimplemented each and every time. Transducers
>> make
>> > it explicit and facilitate re-use and coherent behavior.
>> > For example:
>> > - #collect: requires mapping: (aBlock1 map)
>> > - #select: requires filtering: (aBlock2 filter)
>> >
>> >
>> > ## Compose
>> > In practice, algorithms often require multiple processing steps, e.g.,
>> > mapping only a filtered set of elements.
>> > Transducers are inherently composable, and hereby, allow to make the
>> > combination of steps explicit.
>> > Since transducers do not build intermediate collections, their
>> composition
>> > is memory-efficient.
>> > For example:
>> > - (aBlock1 filter) * (aBlock2 map) "(1.) filter and (2.) map
>> elements"
>> >
>> >
>> > ## Re-Use
>> > Transducers are decoupled from the input and output sources, and
>> hence,
>> > they can be reused in different contexts.
>> > For example:
>> > - enumeration of collections
>> > - processing of streams
>> > - communicating via channels
>> >
>> >
>> >
>> > # Usage by Example
>> >
>> > We build a coin flipping experiment and count the occurrence of heads
>> and
>> > tails.
>> >
>> > First, we associate random numbers with the sides of a coin.
>> >
>> > scale := [:x | (x * 2 + 1) floor] map.
>> > sides := #(heads tails) replace.
>> >
>> > Scale is a transducer that maps numbers x between 0 and 1 to 1 and 2.
>> > Sides is a transducer that replaces the numbers with heads an tails by
>> > lookup in an array.
>> > Next, we choose a number of samples.
>> >
>> > count := 1000 take.
>> >
>> > Count is a transducer that takes 1000 elements from a source.
>> > We keep track of the occurrences of heads an tails using a bag.
>> >
>> > collect := [:bag :c | bag add: c; yourself].
>> >
>> > Collect is binary block (reducing function) that collects events in a
>> bag.
>> > We assemble the experiment by transforming the block using the
>> transducers.
>> >
>> > experiment := (scale * sides * count) transform: collect.
>> >
>> > From left to right we see the steps involved: scale, sides, count and
>> > collect.
>> > Transforming assembles these steps into a binary block (reducing
>> function)
>> > we can use to run the experiment.
>> >
>> > samples := Random new
>> > reduce: experiment
>> > init: Bag new.
>> >
>> > Here, we use #reduce:init:, which is mostly similar to #inject:into:.
>> > To execute a transformation and a reduction together, we can use
>> > #transduce:reduce:init:.
>> >
>> > samples := Random new
>> > transduce: scale * sides * count
>> > reduce: collect
>> > init: Bag new.
>> >
>> > We can also express the experiment as data-flow using #<~.
>> > This enables us to build objects that can be re-used in other
>> experiments.
>> >
>> > coin := sides <~ scale <~ Random new.
>> > flip := Bag <~ count.
>> >
>> > Coin is an eduction, i.e., it binds transducers to a source and
>> > understands #reduce:init: among others.
>> > Flip is a transformed reduction, i.e., it binds transducers to a
>> reducing
>> > function and an initial value.
>> > By sending #<~, we draw further samples from flipping the coin.
>> >
>> > samples := flip <~ coin.
>> >
>> > This yields a new Bag with another 1000 samples.
>> >
>> >
>> >
>> > # Basic Concepts
>> >
>> > ## Reducing Functions
>> >
>> > A reducing function represents a single step in processing a data
>> sequence.
>> > It takes an accumulated result and a value, and returns a new
>> accumulated
>> > result.
>> > For example:
>> >
>> > collect := [:col :e | col add: e; yourself].
>> > sum := #+.
>> >
>> > A reducing function can also be ternary, i.e., it takes an accumulated
>> > result, a key and a value.
>> > For example:
>> >
>> > collect := [:dic :k :v | dict at: k put: v; yourself].
>> >
>> > Reducing functions may be equipped with an optional completing action.
>> > After finishing processing, it is invoked exactly once, e.g., to free
>> > resources.
>> >
>> > stream := [:str :e | str nextPut: each; yourself] completing:
>> #close.
>> > absSum := #+ completing: #abs
>> >
>> > A reducing function can end processing early by signaling Reduced
>> with a
>> > result.
>> > This mechanism also enables the treatment of infinite sources.
>> >
>> > nonNil := [:res :e | e ifNil: [Reduced signalWith: res] ifFalse:
>> [res]].
>> >
>> > The primary approach to process a data sequence is the reducing
>> protocol
>> > with the messages #reduce:init: and #transduce:reduce:init: if
>> transducers
>> > are involved.
>> > The behavior is similar to #inject:into: but in addition it takes care
>> of:
>> > - handling binary and ternary reducing functions,
>> > - invoking the completing action after finishing, and
>> > - stopping the reduction if Reduced is signaled.
>> > The message #transduce:reduce:init: just combines the transformation
>> and
>> > the reducing step.
>> >
>> > However, as reducing functions are step-wise in nature, an application
>> may
>> > choose other means to process its data.
>> >
>> >
>> > ## Reducibles
>> >
>> > A data source is called reducible if it implements the reducing
>> protocol.
>> > Default implementations are provided for collections and streams.
>> > Additionally, blocks without an argument are reducible, too.
>> > This allows to adapt to custom data sources without additional effort.
>> > For example:
>> >
>> > "XStreams adaptor"
>> > xstream := filename reading.
>> > reducible := [[xstream get] on: Incomplete do: [Reduced signal]].
>> >
>> > "natural numbers"
>> > n := 0.
>> > reducible := [n := n+1].
>> >
>> >
>> > ## Transducers
>> >
>> > A transducer is an object that transforms a reducing function into
>> another.
>> > Transducers encapsulate common steps in processing data sequences,
>> such
>> as
>> > map, filter, concatenate, and flatten.
>> > A transducer transforms a reducing function into another via
>> #transform:
>> > in order to add those steps.
>> > They can be composed using #* which yields a new transducer that does
>> both
>> > transformations.
>> > Most transducers require an argument, typically blocks, symbols or
>> numbers:
>> >
>> > square := Map function: #squared.
>> > take := Take number: 1000.
>> >
>> > To facilitate compact notation, the argument types implement
>> corresponding
>> > methods:
>> >
>> > squareAndTake := #squared map * 1000 take.
>> >
>> > Transducers requiring no argument are singletons and can be accessed
>> by
>> > their class name.
>> >
>> > flattenAndDedupe := Flatten * Dedupe.
>> >
>> >
>> >
>> > # Advanced Concepts
>> >
>> > ## Data flows
>> >
>> > Processing a sequence of data can often be regarded as a data flow.
>> > The operator #<~ allows define a flow from a data source through
>> > processing steps to a drain.
>> > For example:
>> >
>> > squares := Set <~ 1000 take <~ #squared map <~ (1 to: 1000).
>> > fileOut writeStream <~ #isSeparator filter <~ fileIn readStream.
>> >
>> > In both examples #<~ is only used to set up the data flow using
>> reducing
>> > functions and transducers.
>> > In contrast to streams, transducers are completely independent from
>> input
>> > and output sources.
>> > Hence, we have a clear separation of reading data, writing data and
>> > processing elements.
>> > - Sources know how to iterate over data with a reducing function,
>> e.g.,
>> > via #reduce:init:.
>> > - Drains know how to collect data using a reducing function.
>> > - Transducers know how to process single elements.
>> >
>> >
>> > ## Reductions
>> >
>> > A reduction binds an initial value or a block yielding an initial
>> value
>> to
>> > a reducing function.
>> > The idea is to define a ready-to-use process that can be applied in
>> > different contexts.
>> > Reducibles handle reductions via #reduce: and #transduce:reduce:
>> > For example:
>> >
>> > sum := #+ init: 0.
>> > sum1 := #(1 1 1) reduce: sum.
>> > sum2 := (1 to: 1000) transduce: #odd filter reduce: sum.
>> >
>> > asSet := [:set :e | set add: e; yourself] initializer: [Set new].
>> > set1 := #(1 1 1) reduce: asSet.
>> > set2 := #(1 to: 1000) transduce: #odd filter reduce: asSet.
>> >
>> > By combining a transducer with a reduction, a process can be further
>> > modified.
>> >
>> > sumOdds := sum <~ #odd filter
>> > setOdds := asSet <~ #odd filter
>> >
>> >
>> > ## Eductions
>> >
>> > An eduction combines a reducible data sources with a transducer.
>> > The idea is to define a transformed (virtual) data source that needs
>> not
>> > to be stored in memory.
>> >
>> > odds1 := #odd filter <~ #(1 2 3) readStream.
>> > odds2 := #odd filter <~ (1 to 1000).
>> >
>> > Depending on the underlying source, eductions can be processed once
>> > (streams, e.g., odds1) or multiple times (collections, e.g., odds2).
>> > Since no intermediate data is stored, transducers actions are lazy,
>> i.e.,
>> > they are invoked each time the eduction is processed.
>> >
>> >
>> >
>> > # Origins
>> >
>> > Transducers is based on the same-named Clojure library and its ideas.
>> > Please see:
>> > http://clojure.org/transducers
>> >
>>
>>
May 31, 2017
Re: [Pharo-users] Morphic or forking bug?
by horrido
Oh, I forgot to mention, the crash dump says I got a segmentation fault.
horrido wrote
> I have a puzzling bug. I've narrowed the scenario down to this code:
>
> Cranky»initA
> a := ((StringMorph contents: '####') color: Color white) position:
> (0@0).
> m addMorph: a
>
> Cranky»initialize
> f := Form fromFileNamed: 'hot_air_balloon_mysticmorning.jpg'.
> m := ImageMorph new.
> m form: f.
> self initA.
> m openInWindowLabeled: 'Cranky'.
> delay := (Delay forSeconds: 5).
> [ [ true ] whileTrue: [ a contents: 0 asString. delay wait ] fork
>
> I can run this application for hours and hours with no problem. However,
> if I run it for a while and then close the application and then save/exit
> the image, the next time I start the image, there is some likelihood it
> will crash dump. The probability is something like 5-10%.
>
> Interestingly, if I remove the statement...
>
> a contents: 0 asString.
>
> from the infinite loop, I've not been able to replicate the crash. Is
> there something wrong with the way I'm updating the contents of the
> StringMorph?
--
View this message in context: http://forum.world.st/Morphic-or-forking-bug-tp4948727p4948728.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
May 31, 2017
Morphic or forking bug?
by horrido
I have a puzzling bug. I've narrowed the scenario down to this code:
Cranky»initA
a := ((StringMorph contents: '####') color: Color white) position: (0@0).
m addMorph: a
Cranky»initialize
f := Form fromFileNamed: 'hot_air_balloon_mysticmorning.jpg'.
m := ImageMorph new.
m form: f.
self initA.
m openInWindowLabeled: 'Cranky'.
delay := (Delay forSeconds: 5).
[ [ true ] whileTrue: [ a contents: 0 asString. delay wait ] fork
I can run this application for hours and hours with no problem. However, if
I run it for a while and then close the application and then save/exit the
image, the next time I start the image, there is some likelihood it will
crash dump. The probability is something like 5-10%.
Interestingly, if I remove the statement...
a contents: 0 asString.
from the infinite loop, I've not been able to replicate the crash. Is there
something wrong with the way I'm updating the contents of the StringMorph?
--
View this message in context: http://forum.world.st/Morphic-or-forking-bug-tp4948727.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
May 31, 2017