From max95812@REDACTED Thu Aug 1 13:06:25 2019 From: max95812@REDACTED (Maximilian Hill) Date: Thu, 1 Aug 2019 13:06:25 +0200 Subject: [erlang-questions] rebar3 default gitignore Message-ID: Hi, I just wondered, why the default .gitignore for rebar3 releases contains files and a directory, specific to IntelliJ IDEA. This is no complain, since I use this it as well. I'm new to erlang/OTP, so I don't have much of an idea about the community, but expected this file to be more generic. From t@REDACTED Thu Aug 1 16:33:23 2019 From: t@REDACTED (Tristan Sloughter) Date: Thu, 01 Aug 2019 08:33:23 -0600 Subject: [erlang-questions] rebar3 default gitignore In-Reply-To: References: Message-ID: <876099d3-f2ca-45a3-893c-59b113c31dd2@www.fastmail.com> Since it is a very small and out of the way file we aren't concerned with making it so small it covers only the basics, which would be just _build, I guess. So we accept reasonable PRs to add coverage of reasonably common ides like Intellij to make it as smooth as possible for getting going with a new project. On Thu, Aug 1, 2019, at 05:11, Maximilian Hill wrote: > Hi, > > I just wondered, why the default .gitignore for rebar3 releases contains > files and a directory, specific to IntelliJ IDEA. > This is no complain, since I use this it as well. > > I'm new to erlang/OTP, so I don't have much of an idea about the > community, but expected this file to be more generic. > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > From v@REDACTED Sat Aug 3 18:14:15 2019 From: v@REDACTED (Valentin Micic) Date: Sat, 3 Aug 2019 18:14:15 +0200 Subject: [erlang-questions] Illegal map key in pattern Message-ID: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> Hi, I am a bit nonplussed with the behaviour of map module?consider the following map: f(MAP), MAP = #{ {12,1} => "some value", {12,2} => "some other value"}. Then, the following works: f(V), case MAP of #{ {1,12} := V} -> V end. "some value? Then, surely, a snippet below should also work... except that it doesn?t: f(DCID), f(SORD), DCID = 12, SORD=1. f(V), case MAP of #{ {DCID, SORD} := V} -> V end. * 1: illegal map key in pattern To make things worse, when I just replace an explicit term, such as {DCID, SORD}, with something like this: f(GRP_KEY), GRP_KEY={DCID, SORD}. f(V), case MAP of #{ GRP_KEY := V} -> V end. "some value? Then the whole thing works again. I would argue that all cases should just work. How come they don?t? Kind regards V/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From raimo+erlang-questions@REDACTED Mon Aug 5 09:29:37 2019 From: raimo+erlang-questions@REDACTED (Raimo Niskanen) Date: Mon, 5 Aug 2019 09:29:37 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> Message-ID: <20190805072937.GA64211@erix.ericsson.se> On Sat, Aug 03, 2019 at 06:14:15PM +0200, Valentin Micic wrote: > Hi, > > I am a bit nonplussed with the behaviour of map module?consider the following map: > > > f(MAP), MAP = #{ {12,1} => "some value", {12,2} => "some other value"}. > > > Then, the following works: > > > f(V), case MAP of #{ {1,12} := V} -> V end. > > "some value? > > > > Then, surely, a snippet below should also work... except that it doesn?t: > > > f(DCID), f(SORD), DCID = 12, SORD=1. > > f(V), case MAP of #{ {DCID, SORD} := V} -> V end. > > * 1: illegal map key in pattern The syntax of your examples makes no sense to me, so I take a shot in the dark on your gripe. fun (K, V, Map) -> case Map of #{ K := V} -> V end end. fun (K, V, Map) -> case Map of #{ {K} := V} -> V end end. fun (K, V, Map) -> K_1 = {K}, case Map of #{ K_1 := V} -> V end end. Try those in the shell and you will find out that the first produces a fun(), the second barfs with "illegal map key in pattern", and the third produces a fun(). From: http://erlang.org/doc/reference_manual/expressions.html#map-expressions section "Maps in Patterns" Matching of key-value associations from maps is done as follows: #{ K := V } = M Here M is any map. The key K must be an expression with bound variables or literals. V can be any pattern with either bound or unbound variables. So, the key must be a literal or a bound variable. It's a known limitation. / Raimo > > > > To make things worse, when I just replace an explicit term, such as {DCID, SORD}, with something like this: > > > f(GRP_KEY), GRP_KEY={DCID, SORD}. > > f(V), case MAP of #{ GRP_KEY := V} -> V end. > > "some value? > > > > Then the whole thing works again. > > I would argue that all cases should just work. > How come they don?t? > > > Kind regards > > V/ > -- / Raimo Niskanen, Erlang/OTP, Ericsson AB From v@REDACTED Mon Aug 5 09:43:10 2019 From: v@REDACTED (Valentin Micic) Date: Mon, 5 Aug 2019 09:43:10 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: <20190805072937.GA64211@erix.ericsson.se> References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> <20190805072937.GA64211@erix.ericsson.se> Message-ID: <01AD71C7-D36D-49AD-AE2E-2A8EAD1C45A3@micic.co.za> Thank you, I guess? > On 05 Aug 2019, at 09:29, Raimo Niskanen wrote: > > On Sat, Aug 03, 2019 at 06:14:15PM +0200, Valentin Micic wrote: >> Hi, >> >> I am a bit nonplussed with the behaviour of map module?consider the following map: >> >> >> f(MAP), MAP = #{ {12,1} => "some value", {12,2} => "some other value"}. >> >> >> Then, the following works: >> >> >> f(V), case MAP of #{ {1,12} := V} -> V end. >> >> "some value? >> >> >> >> Then, surely, a snippet below should also work... except that it doesn?t: >> >> >> f(DCID), f(SORD), DCID = 12, SORD=1. >> >> f(V), case MAP of #{ {DCID, SORD} := V} -> V end. >> >> * 1: illegal map key in pattern > > The syntax of your examples makes no sense to me, so I take a shot in the > dark on your gripe. > > fun (K, V, Map) -> > case Map of > #{ K := V} -> V > end > end. > > fun (K, V, Map) -> > case Map of > #{ {K} := V} -> V > end > end. > > fun (K, V, Map) -> > K_1 = {K}, > case Map of > #{ K_1 := V} -> V > end > end. > > Try those in the shell and you will find out that the first produces a > fun(), the second barfs with "illegal map key in pattern", and the third > produces a fun(). > > From: > http://erlang.org/doc/reference_manual/expressions.html#map-expressions > section "Maps in Patterns" > > Matching of key-value associations from maps is done as follows: > > #{ K := V } = M > > Here M is any map. The key K must be an expression with bound > variables or literals. V can be any pattern with either bound > or unbound variables. > > So, the key must be a literal or a bound variable. > It's a known limitation. > > / Raimo > > >> >> >> >> To make things worse, when I just replace an explicit term, such as {DCID, SORD}, with something like this: >> >> >> f(GRP_KEY), GRP_KEY={DCID, SORD}. >> >> f(V), case MAP of #{ GRP_KEY := V} -> V end. >> >> "some value? >> >> >> >> Then the whole thing works again. >> >> I would argue that all cases should just work. >> How come they don?t? >> >> >> Kind regards >> >> V/ >> > > > -- > > / Raimo Niskanen, Erlang/OTP, Ericsson AB > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions From z@REDACTED Mon Aug 5 10:35:11 2019 From: z@REDACTED (Danil Zagoskin) Date: Mon, 5 Aug 2019 11:35:11 +0300 Subject: [erlang-questions] Loading a copy of a module under a different name In-Reply-To: References: Message-ID: Hi! Maybe this approach to a module renaming will be useful for you: https://github.com/klajo/hacks/blob/master/beam/src/beam_renamer.erl A long while ago I've used beam_renamer in my experiments: https://github.com/stolen/modhack ? to inject custom code in other module. I don't remember if that worked with lists module though. As Dmitry said, it may be tricky to fiddle with NIFs and BIFs. On Mon, Jul 29, 2019 at 2:56 PM Luca Tansini wrote: > Hi all, > > I?m trying to load into the VM a copy of a module under a different name. > The way I?m trying to do it is: > - get the binary of the module with code:get_object_code(mod_name) > - replace the module name inside the binary (otherwise the code loader > won?t accept it) > - reload it with code:load_binary(new_name, ??, RenamedBinary) > > here is some sample code showing the approach: > https://pastebin.com/HpdUR0eU. > > This approach seems to work as long as the original module doesn?t contain > any NIFs. > In that case the module is still loaded (not always, I?ve found at least > one exception, more below), but then gives runtime errors when NIFs are > trying to be run. > > For instance this is what happens with the lists module: > > >> module_cp:load_module_copy(lists). > {module,xists} > >> xists:seq(1,10). > [1,2,3,4,5,6,7,8,9,10] > >> xists:reverse([1,2,3,4]). > ** exception error: undefined function erlang:nif_error/1 > in function xists:reverse/2 (xists.erl, line 95) > > > For the erlang module instead, even the code loading fails: > > >> module_cp:load_module_copy(erlang). > {error,badfile} > > =ERROR REPORT==== 26-Jul-2019::13:10:11 === > Loading of failed: badfile > > =ERROR REPORT==== 26-Jul-2019::13:10:11 === > beam/beam_load.c(2284): Error loading function xrlang:garbage_collect/2: > op bif0 u x: > no specific operation found > > > I?m not very familiar with how NIFs work and are loaded, but is there a > workaround for this? > Maybe renaming only the module attribute is not enough. > I?m on MacOS running Erlang/OTP 20 [erts-9.3]. > > Thank you > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -- Danil Zagoskin | z@REDACTED -------------- next part -------------- An HTML attachment was scrubbed... URL: From per@REDACTED Mon Aug 5 11:03:56 2019 From: per@REDACTED (Per Hedeland) Date: Mon, 5 Aug 2019 11:03:56 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: <20190805072937.GA64211@erix.ericsson.se> References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> <20190805072937.GA64211@erix.ericsson.se> Message-ID: <32a6fec8-49e7-4770-52b6-7887f7ae229a@hedeland.org> On 2019-08-05 09:29, Raimo Niskanen wrote: > On Sat, Aug 03, 2019 at 06:14:15PM +0200, Valentin Micic wrote: >> Hi, >> >> I am a bit nonplussed with the behaviour of map module&consider the following map: >> >> >> f(MAP), MAP = #{ {12,1} => "some value", {12,2} => "some other value"}. >> >> >> Then, the following works: >> >> >> f(V), case MAP of #{ {1,12} := V} -> V end. >> >> "some value" >> >> >> >> Then, surely, a snippet below should also work... except that it doesnt: >> >> >> f(DCID), f(SORD), DCID = 12, SORD=1. >> >> f(V), case MAP of #{ {DCID, SORD} := V} -> V end. >> >> * 1: illegal map key in pattern > > The syntax of your examples makes no sense to me, so I take a shot in the > dark on your gripe. It's just "shell syntax", try it:-) - the f/1 is the shell's "forget" function, to ensure that the variable is unbound. > fun (K, V, Map) -> > case Map of > #{ K := V} -> V > end > end. > > fun (K, V, Map) -> > case Map of > #{ {K} := V} -> V > end > end. > > fun (K, V, Map) -> > K_1 = {K}, > case Map of > #{ K_1 := V} -> V > end > end. > > Try those in the shell and you will find out that the first produces a > fun(), the second barfs with "illegal map key in pattern", and the third > produces a fun(). > > From: > http://erlang.org/doc/reference_manual/expressions.html#map-expressions > section "Maps in Patterns" > > Matching of key-value associations from maps is done as follows: > > #{ K := V } = M > > Here M is any map. The key K must be an expression with bound > variables or literals. V can be any pattern with either bound > or unbound variables. > > So, the key must be a literal or a bound variable. Hm, that's not what the documentation that you quote says - surely, if K is a bound variable, {K} is "an expression with bound variables", as is {DCID, SORD} in Valentin's case. And of course there's no way the variableS can be plural if not combined into an expression somehow... > It's a known limitation. So it seems the documentation is wrong, and should drop the "expression" and plurals: "The key K must be a bound variable or a literal." (as you said). --Per > / Raimo > > >> >> >> >> To make things worse, when I just replace an explicit term, such as {DCID, SORD}, with something like this: >> >> >> f(GRP_KEY), GRP_KEY={DCID, SORD}. >> >> f(V), case MAP of #{ GRP_KEY := V} -> V end. >> >> "some value >> >> >> >> Then the whole thing works again. >> >> I would argue that all cases should just work. >> How come they dont? >> >> >> Kind regards >> >> V/ >> > > From v@REDACTED Mon Aug 5 12:28:48 2019 From: v@REDACTED (Valentin Micic) Date: Mon, 5 Aug 2019 12:28:48 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: <32a6fec8-49e7-4770-52b6-7887f7ae229a@hedeland.org> References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> <20190805072937.GA64211@erix.ericsson.se> <32a6fec8-49e7-4770-52b6-7887f7ae229a@hedeland.org> Message-ID: <547DFD68-A005-4C1E-8039-88A315F0F8C5@micic.co.za> > On 05 Aug 2019, at 11:03, Per Hedeland wrote: > > On 2019-08-05 09:29, Raimo Niskanen wrote: >> On Sat, Aug 03, 2019 at 06:14:15PM +0200, Valentin Micic wrote: >>> Hi, >>> >>> I am a bit nonplussed with the behaviour of map module&consider the following map: >>> >>> >>> f(MAP), MAP = #{ {12,1} => "some value", {12,2} => "some other value"}. >>> >>> >>> Then, the following works: >>> >>> >>> f(V), case MAP of #{ {1,12} := V} -> V end. >>> "some value" >>> >>> >>> >>> Then, surely, a snippet below should also work... except that it doesnt: >>> >>> >>> f(DCID), f(SORD), DCID = 12, SORD=1. >>> >>> f(V), case MAP of #{ {DCID, SORD} := V} -> V end. >>> >>> * 1: illegal map key in pattern >> The syntax of your examples makes no sense to me, so I take a shot in the >> dark on your gripe. > > It's just "shell syntax", try it:-) - the f/1 is the shell's "forget" > function, to ensure that the variable is unbound. > >> fun (K, V, Map) -> >> case Map of >> #{ K := V} -> V >> end >> end. >> fun (K, V, Map) -> >> case Map of >> #{ {K} := V} -> V >> end >> end. >> fun (K, V, Map) -> >> K_1 = {K}, >> case Map of >> #{ K_1 := V} -> V >> end >> end. >> Try those in the shell and you will find out that the first produces a >> fun(), the second barfs with "illegal map key in pattern", and the third >> produces a fun(). >> From: >> http://erlang.org/doc/reference_manual/expressions.html#map-expressions >> section "Maps in Patterns" >> Matching of key-value associations from maps is done as follows: >> #{ K := V } = M >> Here M is any map. The key K must be an expression with bound >> variables or literals. V can be any pattern with either bound >> or unbound variables. >> So, the key must be a literal or a bound variable. > > Hm, that's not what the documentation that you quote says - surely, if > K is a bound variable, {K} is "an expression with bound variables", as > is {DCID, SORD} in Valentin's case. And of course there's no way the > variableS can be plural if not combined into an expression somehow... > >> It's a known limitation. > > So it seems the documentation is wrong, and should drop the > "expression" and plurals: "The key K must be a bound variable or a > literal." (as you said). > > ?Per Thank you Per for articulating my issue in a way I wasn?t able to do. :-) Indeed, documentation seems a bit misleading. When they are referencing a plural (bound variables), they are probably referring to a multitude of ?single? variables used as keys to a multitude of maps. But, documentation aside ? that could be corrected; do you think that this kind of implementation is in line with a principle of least astonishment? V/ > >> / Raimo >>> >>> >>> >>> To make things worse, when I just replace an explicit term, such as {DCID, SORD}, with something like this: >>> >>> >>> f(GRP_KEY), GRP_KEY={DCID, SORD}. >>> >>> f(V), case MAP of #{ GRP_KEY := V} -> V end. >>> >>> "some value >>> >>> >>> >>> Then the whole thing works again. >>> >>> I would argue that all cases should just work. >>> How come they dont? >>> >>> >>> Kind regards >>> >>> V/ >>> > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions From per@REDACTED Mon Aug 5 13:11:36 2019 From: per@REDACTED (Per Hedeland) Date: Mon, 5 Aug 2019 13:11:36 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: <547DFD68-A005-4C1E-8039-88A315F0F8C5@micic.co.za> References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> <20190805072937.GA64211@erix.ericsson.se> <32a6fec8-49e7-4770-52b6-7887f7ae229a@hedeland.org> <547DFD68-A005-4C1E-8039-88A315F0F8C5@micic.co.za> Message-ID: <9ffac6d6-5e95-d70d-c1bb-9a95e755dccc@hedeland.org> On 2019-08-05 12:28, Valentin Micic wrote: >> On 05 Aug 2019, at 11:03, Per Hedeland wrote: >> >> On 2019-08-05 09:29, Raimo Niskanen wrote: >>> On Sat, Aug 03, 2019 at 06:14:15PM +0200, Valentin Micic wrote: >>>> Hi, >>>> >>>> I am a bit nonplussed with the behaviour of map module&consider the following map: >>>> >>>> >>>> f(MAP), MAP = #{ {12,1} => "some value", {12,2} => "some other value"}. >>>> >>>> >>>> Then, the following works: >>>> >>>> >>>> f(V), case MAP of #{ {1,12} := V} -> V end. >>>> "some value" >>>> >>>> >>>> >>>> Then, surely, a snippet below should also work... except that it doesnt: >>>> >>>> >>>> f(DCID), f(SORD), DCID = 12, SORD=1. >>>> >>>> f(V), case MAP of #{ {DCID, SORD} := V} -> V end. >>>> >>>> * 1: illegal map key in pattern >>> The syntax of your examples makes no sense to me, so I take a shot in the >>> dark on your gripe. >> >> It's just "shell syntax", try it:-) - the f/1 is the shell's "forget" >> function, to ensure that the variable is unbound. >> >>> fun (K, V, Map) -> >>> case Map of >>> #{ K := V} -> V >>> end >>> end. >>> fun (K, V, Map) -> >>> case Map of >>> #{ {K} := V} -> V >>> end >>> end. >>> fun (K, V, Map) -> >>> K_1 = {K}, >>> case Map of >>> #{ K_1 := V} -> V >>> end >>> end. >>> Try those in the shell and you will find out that the first produces a >>> fun(), the second barfs with "illegal map key in pattern", and the third >>> produces a fun(). >>> From: >>> http://erlang.org/doc/reference_manual/expressions.html#map-expressions >>> section "Maps in Patterns" >>> Matching of key-value associations from maps is done as follows: >>> #{ K := V } = M >>> Here M is any map. The key K must be an expression with bound >>> variables or literals. V can be any pattern with either bound >>> or unbound variables. >>> So, the key must be a literal or a bound variable. >> >> Hm, that's not what the documentation that you quote says - surely, if >> K is a bound variable, {K} is "an expression with bound variables", as >> is {DCID, SORD} in Valentin's case. And of course there's no way the >> variableS can be plural if not combined into an expression somehow... >> >>> It's a known limitation. >> >> So it seems the documentation is wrong, and should drop the >> "expression" and plurals: "The key K must be a bound variable or a >> literal." (as you said). >> >> --Per > > Thank you Per for articulating my issue in a way I wasnt able to do. :-) > > Indeed, documentation seems a bit misleading. When they are referencing a plural (bound variables), they are probably referring to a multitude of "single" variables used as keys to a multitude of maps. I could agree with that, if the sentence didn't start with "The key K must be...", clearly referencing the single key K in the single map M in the specific expression "#{ K := V } = M". > But, documentation aside  that could be corrected; do you think that this kind of implementation is in line with a principle of least astonishment? Well, I know basically nothing about how maps are implemented, but *I* would certainly be less astonished by the limitation described in the documentation (it seems entirely reasonable) than by the actual limitation, since in most other cases I can think of, you can use "an expression with bound variables" wherever you can use "a bound variable". But maybe it's "just" something that was a challenge to implement, and will be fixed to match the current documentation in a future release... --Per > V/ > >> >>> / Raimo >>>> >>>> >>>> >>>> To make things worse, when I just replace an explicit term, such as {DCID, SORD}, with something like this: >>>> >>>> >>>> f(GRP_KEY), GRP_KEY={DCID, SORD}. >>>> >>>> f(V), case MAP of #{ GRP_KEY := V} -> V end. >>>> >>>> "some value >>>> >>>> >>>> >>>> Then the whole thing works again. >>>> >>>> I would argue that all cases should just work. >>>> How come they dont? >>>> >>>> >>>> Kind regards >>>> >>>> V/ >>>> >> >> _______________________________________________ >> erlang-questions mailing list >> erlang-questions@REDACTED >> http://erlang.org/mailman/listinfo/erlang-questions > From raimo+erlang-questions@REDACTED Mon Aug 5 13:45:24 2019 From: raimo+erlang-questions@REDACTED (Raimo Niskanen) Date: Mon, 5 Aug 2019 13:45:24 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: <9ffac6d6-5e95-d70d-c1bb-9a95e755dccc@hedeland.org> References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> <20190805072937.GA64211@erix.ericsson.se> <32a6fec8-49e7-4770-52b6-7887f7ae229a@hedeland.org> <547DFD68-A005-4C1E-8039-88A315F0F8C5@micic.co.za> <9ffac6d6-5e95-d70d-c1bb-9a95e755dccc@hedeland.org> Message-ID: <20190805114524.GA5959@erix.ericsson.se> On Mon, Aug 05, 2019 at 01:11:36PM +0200, Per Hedeland wrote: > On 2019-08-05 12:28, Valentin Micic wrote: > >> On 05 Aug 2019, at 11:03, Per Hedeland wrote: > >> > >> On 2019-08-05 09:29, Raimo Niskanen wrote: > >>> On Sat, Aug 03, 2019 at 06:14:15PM +0200, Valentin Micic wrote: > >>>> Hi, > >>>> > >>>> I am a bit nonplussed with the behaviour of map module&consider the following map: > >>>> > >>>> > >>>> f(MAP), MAP = #{ {12,1} => "some value", {12,2} => "some other value"}. > >>>> > >>>> > >>>> Then, the following works: > >>>> > >>>> > >>>> f(V), case MAP of #{ {1,12} := V} -> V end. > >>>> "some value" > >>>> > >>>> > >>>> > >>>> Then, surely, a snippet below should also work... except that it doesnt: > >>>> > >>>> > >>>> f(DCID), f(SORD), DCID = 12, SORD=1. > >>>> > >>>> f(V), case MAP of #{ {DCID, SORD} := V} -> V end. > >>>> > >>>> * 1: illegal map key in pattern > >>> The syntax of your examples makes no sense to me, so I take a shot in the > >>> dark on your gripe. > >> > >> It's just "shell syntax", try it:-) - the f/1 is the shell's "forget" > >> function, to ensure that the variable is unbound. Sorry, just back from vacation... > >> > >>> fun (K, V, Map) -> > >>> case Map of > >>> #{ K := V} -> V > >>> end > >>> end. > >>> fun (K, V, Map) -> > >>> case Map of > >>> #{ {K} := V} -> V > >>> end > >>> end. > >>> fun (K, V, Map) -> > >>> K_1 = {K}, > >>> case Map of > >>> #{ K_1 := V} -> V > >>> end > >>> end. > >>> Try those in the shell and you will find out that the first produces a > >>> fun(), the second barfs with "illegal map key in pattern", and the third > >>> produces a fun(). > >>> From: > >>> http://erlang.org/doc/reference_manual/expressions.html#map-expressions > >>> section "Maps in Patterns" > >>> Matching of key-value associations from maps is done as follows: > >>> #{ K := V } = M > >>> Here M is any map. The key K must be an expression with bound > >>> variables or literals. V can be any pattern with either bound > >>> or unbound variables. > >>> So, the key must be a literal or a bound variable. > >> > >> Hm, that's not what the documentation that you quote says - surely, if > >> K is a bound variable, {K} is "an expression with bound variables", as > >> is {DCID, SORD} in Valentin's case. And of course there's no way the > >> variableS can be plural if not combined into an expression somehow... > >> > >>> It's a known limitation. > >> > >> So it seems the documentation is wrong, and should drop the > >> "expression" and plurals: "The key K must be a bound variable or a > >> literal." (as you said). Good catch! I read it as I knew it works, not as it stood. > >> > >> --Per > > > > Thank you Per for articulating my issue in a way I wasnt able to do. :-) > > > > Indeed, documentation seems a bit misleading. When they are referencing a plural (bound variables), they are probably referring to a multitude of "single" variables used as keys to a multitude of maps. > > I could agree with that, if the sentence didn't start with "The key K > must be...", clearly referencing the single key K in the single map M > in the specific expression "#{ K := V } = M". > > > But, documentation aside  that could be corrected; do you think that this kind of implementation is in line with a principle of least astonishment? > > Well, I know basically nothing about how maps are implemented, but *I* > would certainly be less astonished by the limitation described in the > documentation (it seems entirely reasonable) than by the actual > limitation, since in most other cases I can think of, you can use "an > expression with bound variables" wherever you can use "a bound > variable". > > But maybe it's "just" something that was a challenge to implement, and > will be fixed to match the current documentation in a future release... I think it is precisely like that. It is documented as it was intended, but implementing it was a challenge so it got only partly implemented. (constructing a new term for map lookup in the context of a pattern match proved an unexpectedly hard problem, I guess) So it is a known limitation, to us that know it ;-) unfortunately not nicely documented, and the goal is to fix it some day... http://erlang.org/pipermail/erlang-questions/2016-May/089269.html / Raimo > > --Per > > > V/ > > > >> > >>> / Raimo > >>>> > >>>> > >>>> > >>>> To make things worse, when I just replace an explicit term, such as {DCID, SORD}, with something like this: > >>>> > >>>> > >>>> f(GRP_KEY), GRP_KEY={DCID, SORD}. > >>>> > >>>> f(V), case MAP of #{ GRP_KEY := V} -> V end. > >>>> > >>>> "some value > >>>> > >>>> > >>>> > >>>> Then the whole thing works again. > >>>> > >>>> I would argue that all cases should just work. > >>>> How come they dont? > >>>> > >>>> > >>>> Kind regards > >>>> > >>>> V/ > >>>> > >> > >> _______________________________________________ > >> erlang-questions mailing list > >> erlang-questions@REDACTED > >> http://erlang.org/mailman/listinfo/erlang-questions > > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions -- / Raimo Niskanen, Erlang/OTP, Ericsson AB From sperber@REDACTED Mon Aug 5 17:07:32 2019 From: sperber@REDACTED (Michael Sperber) Date: Mon, 05 Aug 2019 17:07:32 +0200 Subject: [erlang-questions] Summer BOB 2019 Final Call for Participation (Aug 21, Berlin) Message-ID: ================================================================================ Summer BOB 2019 Conference ?What happens if we simply use what?s best?? August 21, 2019, Berlin co-located with ICFP 2019 http://bobkonf.de/2019-summer/ Program: http://bobkonf.de/2019-summer/program.html Registration: http://bobkonf.de/2019-summer/registration.html ================================================================================ Are you interested in technologies beyond the mainstream, that are a pleasure to use, and effective at getting the job done? BOB is the forum for developers, architects and builders to explore and discover the best tools available today for building software. Our goal is for all participants to leave the conference with new ideas to improve development back at the ranch. Summer BOB is a one-time-only event, in the spirit of the spectacular Winter BOB. The International Conference on Functional Programming is coming to town, and Summer BOB will be right in the middle of it, on the last day of ICFP proper, prior to all the workshops. BOB participants will be able to attend ICFP talks on Aug 21 and vice versa. We are committed to diversity: We aim at exploring a wide range of tools in a welcoming and friendly crowd of diverse people. To that end, a number of support options for participants from groups under-represented in tech are available. Summer BOB will feature two tracks: one from practitioners, and one from researchers, designed to cross-pollinate and inspire. Topics include distributed programming, testing, linear algebra, functional design patterns, type systems, formal methods, and interactive development: Using Formal Methods to Eliminate Exploitable Bugs Kathleen Fisher Purely functional distributed programming for collaborative applications Adriaan Leijnse Statistical testing of software Stevan Andjelkovic Dependent Types in Haskell Stephanie Weirich >From idea to working product in 7 days Philipp Maier In Search of Software Perfection Xavier Leroy Expressive Linear Algebra in Haskell Henning Thielemann Type-driven Development in Action Edwin Brady Functional Design Patterns Franz Thoma Liquidate your Assets Niki Vazou Scala Type Classes Alexey Novakov Types for Protocols Peter Thiemann Creating maintainable mobile games in Haskell Christina Zeller A Functional Reboot for Deep Learning Conal Elliott From peter.james.morgan@REDACTED Tue Aug 6 13:22:29 2019 From: peter.james.morgan@REDACTED (Peter Morgan) Date: Tue, 6 Aug 2019 12:22:29 +0100 Subject: [erlang-questions] gen_statem: next event internal and reply In-Reply-To: <20190731123621.GA14338@erix.ericsson.se> References: <76B140E6-CA4B-41B8-AE62-A2573944EB2C@gmail.com> <20190731100014.GA81508@erix.ericsson.se> <20190731123621.GA14338@erix.ericsson.se> Message-ID: <5561A70F-0266-4BF2-9324-5A6427A0B420@gmail.com> Hi Raimo, > On 31 Jul 2019, at 13:36, Raimo Niskanen wrote: > > I have checked in a branch in the daily builds that clarifies > the documentation for transition_option() to be more explicit > about when replies are sent, and some other stuff. > > / Raimo > Thanks very much for this. Making the documented reply order more explicit would be perfect. I found a couple of instances of: {keep_state_and_data, [nei(work), {reply, From, ok}]}; and: {keep_state_and_data, [{reply, From, ok}, nei(work)]}; Where the _assumption_ was that the order would be honoured (it is a list!). In the majority of cases that I?ve found it didn't matter - in one case the call was immediately followed by a terminate_child on that process, causing (sometimes) an unclean shutdown. BTW - We?ve not seen any async timer related issues in 22 that we were seeing in earlier 21s. Thanks again for your speedy help on that issue too, much appreciated! Regards, Peter. From raimo+erlang-questions@REDACTED Tue Aug 6 13:52:32 2019 From: raimo+erlang-questions@REDACTED (Raimo Niskanen) Date: Tue, 6 Aug 2019 13:52:32 +0200 Subject: [erlang-questions] gen_statem: next event internal and reply In-Reply-To: <5561A70F-0266-4BF2-9324-5A6427A0B420@gmail.com> References: <76B140E6-CA4B-41B8-AE62-A2573944EB2C@gmail.com> <20190731100014.GA81508@erix.ericsson.se> <20190731123621.GA14338@erix.ericsson.se> <5561A70F-0266-4BF2-9324-5A6427A0B420@gmail.com> Message-ID: <20190806115232.GA97768@erix.ericsson.se> On Tue, Aug 06, 2019 at 12:22:29PM +0100, Peter Morgan wrote: > Hi Raimo, > > > On 31 Jul 2019, at 13:36, Raimo Niskanen wrote: > > > > I have checked in a branch in the daily builds that clarifies > > the documentation for transition_option() to be more explicit > > about when replies are sent, and some other stuff. > > > > / Raimo > > > > > Thanks very much for this. Making the documented reply order more explicit would be perfect. I found a couple of instances of: I try to think of every question as a potential bug report on the documentation. > > {keep_state_and_data, [nei(work), {reply, From, ok}]}; > > and: > > {keep_state_and_data, [{reply, From, ok}, nei(work)]}; > > Where the _assumption_ was that the order would be honoured (it is a list!). In the majority of cases that I?ve found it didn't matter - in one case the call was immediately followed by a terminate_child on that process, causing (sometimes) an unclean shutdown. I/We was/were thinking about letting Actions be a map() instead, and in hindsight that may have been better, but at that time it felt too esoteric... > > BTW - We?ve not seen any async timer related issues in 22 that we were seeing in earlier 21s. Thanks again for your speedy help on that issue too, much appreciated! Glad to hear! Thank you for the update! > > Regards, > Peter. > -- / Raimo Niskanen, Erlang/OTP, Ericsson AB From cean.ebengt@REDACTED Fri Aug 9 08:42:29 2019 From: cean.ebengt@REDACTED (bengt) Date: Fri, 9 Aug 2019 08:42:29 +0200 Subject: [erlang-questions] Lots of epmd in pod Message-ID: <2A01E75F-7BD5-4C56-8C0F-6EF930EAA2DB@gmail.com> Greetings, There is an Erlang release(*) running in a Kubernetes pod. When I use the start script (even if it is only to see the arguments) I get more epmd processes(**). Is that just me? A known problem that can be ignored? Worth investigation? Best Wishes, bengt (*) The Docker file has: erlang:21.3.8.5-alpine and alpine:3.9 (one for build and one for container) Build command: RUN rebar3 as prod release The rebar.config: {relx, [{release, { 'ercdf', "1.3.7" }, [ercdf, recon, observer_cli]}, {dev_mode, true}, {include_erts, false}, {extended_start_script, true}] }. (**) Example after having kubectl exec'd: # ps | grep epmd | wc 46 186 1326 # /opt/ercdf/bin/ercdf remote_console Erlang/OTP 21 [erts-10.3.5.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] Eshell V10.3.5.4 (abort with ^G) User switch command --> q # ps | grep epmd | wc 58 234 1662 Sample of the set of processes that grows 2136 root 0:00 [erl_child_setup] 2166 root 0:00 [inet_gethost] 2226 root 0:00 [epmd] 2227 root 0:00 [epmd] From bryan.hunt@REDACTED Fri Aug 9 12:35:00 2019 From: bryan.hunt@REDACTED (Bryan Hunt) Date: Fri, 9 Aug 2019 11:35:00 +0100 Subject: [erlang-questions] Lots of epmd in pod Message-ID: I bet it?s zombie processes - the epmd process is not being reaped. https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ The epmd will be cleaned up when the pod terminates. Docker fixed this by adding an ?init option which runs the tini init process https://stackoverflow.com/a/50819443/9958902 Kubernetes does not start docker containers with this option You can use tini as a tiny init process to solve this issue - it?s already an alpine package. https://github.com/krallin/tini -- Code Sync & Erlang Solutions Conferences Code BEAM Lite BD - Budapest: 20 September 2019 Code BEAM Lite NYC - NYC: 01 October 2019 Code BEAM Lite - Berlin: 11 October 2019 RabbitMQ Summit - London: 4 November 2019 Code Mesh LDN - London: 7-8 November 2019 Code BEAM Lite India - Bangalore: 14 November 2019 Code BEAM Lite AMS - Amsterdam: 28 November 2019 Lambda Days - Krak?w: 13-14 February 2020 Code BEAM SF - San Francisco: 5-6 March 2020 *Erlang Solutions cares about your data and privacy; please find all details about the basis for communicating with you and the way we process your data in our?**Privacy Policy* *.You can update your email preferences or opt-out from receiving Marketing emails?here .* -------------- next part -------------- An HTML attachment was scrubbed... URL: From t@REDACTED Fri Aug 9 15:38:40 2019 From: t@REDACTED (Tristan Sloughter) Date: Fri, 09 Aug 2019 07:38:40 -0600 Subject: [erlang-questions] Lots of epmd in pod In-Reply-To: References: Message-ID: <589b78a8-4fbe-4b46-b437-6acde21f15ec@www.fastmail.com> Based on the output this is likely the issue but why are the epmd processes going down in the first place? Usually the first one keeps running and no new ones are created, so this issue of reaping doesn't come up. Another option is to not use epmd when running in kubernetes. There aren't port issues in k8s so it isn't needed. Checkout https://github.com/oltarasenko/epmdless for this. The only catch is you need to set the env var `EPMDLESS_REMSH_PORT` to the port used for distribution so that remote_console works the same as before. I'll get something written up about using this in kubernetes soon. Tristan On Fri, Aug 9, 2019, at 04:35, Bryan Hunt wrote: > I bet it?s zombie processes - the epmd process is not being reaped. > > https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ > > The epmd will be cleaned up when the pod terminates. > > Docker fixed this by adding an ?init option which runs the tini init process > > https://stackoverflow.com/a/50819443/9958902 > > Kubernetes does not start docker containers with this option > > You can use tini as a tiny init process to solve this issue - it?s already an alpine package. > > > https://github.com/krallin/tini > > > > > > *Code Sync & Erlang Solutions Conferences* > Code BEAM Lite BD - Budapest: 20 September 2019 > Code BEAM Lite NYC - NYC: 01 October 2019 > Code BEAM Lite - Berlin: 11 October 2019 > RabbitMQ Summit - London: 4 November 2019 > Code Mesh LDN - London: 7-8 November 2019 > Code BEAM Lite India - Bangalore: 14 November 2019 > Code BEAM Lite AMS - Amsterdam: 28 November 2019 > Lambda Days - Krak?w: 13-14 February 2020 > Code BEAM SF - San Francisco: 5-6 March 2020 > > **Erlang Solutions cares about your data and privacy; please find all details about the basis for communicating with you and the way we process your data in our **Privacy Policy* *.You can update your email preferences or opt-out from receiving Marketing emails here .** > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From g@REDACTED Mon Aug 12 03:10:11 2019 From: g@REDACTED (Guilherme Andrade) Date: Mon, 12 Aug 2019 02:10:11 +0100 Subject: [erlang-questions] [ANN] locus: Geolocation and ASN lookup of IP addresses In-Reply-To: References: Message-ID: Hello list, Locus 1.7.0, a geolocation library built on top of MaxMind GeoLite2, was released today. Added: - stacktrace of caught exceptions to event reporting (including custom logger) - ability of launching database loaders under library consumers' own supervisors - `wait_for_loaders/2` method for concurrently waiting on multiple database loaders Changed: - log level of HTTP and filesystem database loading failures from warning to error - HTTP and filesystem loaders into a common loader codebase - caching of HTTP databases as to store and load compressed `.mmdb` files rather than tarballs - supervision structure as to launch database loaders as transient processes under a new `simple_one_for_one` supervisor - dependency versions: - `certifi` [2.4.2 => 2.5.1] - `ssl_verify_fun` [1.1.4 => 1.1.5] Removed: - support for OTP 17.4 and 17.5 - undocumented support for rebar 2 - half-baked and unwarranted support for `file://`-prefixed URLs Fixed: - case-sensitive pattern of `.mmdb` file extensions within tarballs - overly verbose `logger` messages on OTP 21.1+ - HTTPS certificate validation test cases on OTP 22 * Hex package: https://hex.pm/packages/locus/1.7.0 * Documentation: https://hexdocs.pm/locus/1.7.0/ * Source code (GitHub): https://github.com/g-andrade/locus/tree/1.7.0 * Source code (GitLab): https://gitlab.com/g-andrade/locus/tree/1.7.0 -- Guilherme -------------- next part -------------- An HTML attachment was scrubbed... URL: From g@REDACTED Mon Aug 12 03:17:43 2019 From: g@REDACTED (Guilherme Andrade) Date: Mon, 12 Aug 2019 02:17:43 +0100 Subject: [erlang-questions] [ANN] locus: Geolocation and ASN lookup of IP addresses In-Reply-To: References: Message-ID: And lest I forget: On Mon, 12 Aug 2019 at 02:10, Guilherme Andrade wrote: > Added: > - stacktrace of caught exceptions to event reporting (including custom > logger) > - ability of launching database loaders under library consumers' own > supervisors > - `wait_for_loaders/2` method for concurrently waiting on multiple > database loaders > - ability of loading databases from uncompressed tarballs (`.tar` files) - ability of loading unpacked databases (`.mmdb` and `.mmdb.gz` files) -- Guilherme -------------- next part -------------- An HTML attachment was scrubbed... URL: From oliver.bollmann@REDACTED Mon Aug 12 14:16:52 2019 From: oliver.bollmann@REDACTED (Oliver Bollmann) Date: Mon, 12 Aug 2019 14:16:52 +0200 Subject: [erlang-questions] ets:select_delete not atomic? Message-ID: Hi, EtsName = ets:new(test,[named_table,ordered_set]), Res = ets:select_delete(EtsName,[{{Key},[],[true]}]). Res should be 1 or 0! But if i do this with a lot of process, at the same time, it happend that two process get 1! Start with: ets:insert(EtsName,{Key}). Process One: ets:select_delete(EtsName,[{{Key},[],[true]}]). Process Two: ets:select_delete(EtsName,[{{Key},[],[true]}]). Process*One **get 1* AND Process*Two get 1*, with the same key, of course! Is this correct? -- Gr??e Oliver Bollmann -------------- next part -------------- An HTML attachment was scrubbed... URL: From S.J.Thompson@REDACTED Mon Aug 12 14:33:55 2019 From: S.J.Thompson@REDACTED (Simon Thompson) Date: Mon, 12 Aug 2019 13:33:55 +0100 Subject: [erlang-questions] Research Associate at Kent in Trustworthy Refactoring Message-ID: <5B9C56E6-34C2-4553-845C-141275DAB55A@kent.ac.uk> We are seeking to recruit an enthusiastic Research Associate to join the final year of the EPSRC project ?Trustworthy Refactoring?. The overall goal of this project is to investigate the design and construction of trustworthy refactoring tools: this means that when refactorings are performed, the tools will provide strong evidence that the refactoring has not changed the behaviour of the code, built on a solid theoretical understanding of the semantics of the language, thus establishing a step change in the practice of refactoring. If you have have a PhD in Computer Science, awarded or nearing completion, experience in functional programming (e.g. Haskell/ML/Erlang/?) and experience of using a proof assistant (e.g. Coq/Isabelle/HOL/?), you have what we?re looking for. More details about the project are here: https://jobs.kent.ac.uk/vacancy.aspx?ref=STM-047-19 If you have any questions about the post do contact one of us by email: Scott Owens (s.a.owens@REDACTED) and Simon Thompson (s.j.thompson@REDACTED) : we look forward to hearing from you. Scott and Simon Simon Thompson | Professor of Logic and Computation School of Computing | University of Kent | Canterbury, CT2 7NF, UK s.j.thompson@REDACTED | M +44 7986 085754 | W www.cs.kent.ac.uk/~sjt From sverker@REDACTED Mon Aug 12 16:33:44 2019 From: sverker@REDACTED (Sverker Eriksson) Date: Mon, 12 Aug 2019 16:33:44 +0200 Subject: [erlang-questions] ets:select_delete not atomic? In-Reply-To: References: Message-ID: <1565620424.11130.11.camel@erlang.org> On m?n, 2019-08-12 at 14:16 +0200, Oliver Bollmann wrote: > Hi, > > EtsName = ets:new(test,[named_table,ordered_set]), > Res = ets:select_delete(EtsName,[{{Key},[],[true]}]). > > Res should be 1 or 0! > > But if i do this with a lot of process, at the same time, > it happend that two process get 1! > > Start with: ets:insert(EtsName,{Key}). > > Process One: ets:select_delete(EtsName,[{{Key},[],[true]}]). > Process Two: ets:select_delete(EtsName,[{{Key},[],[true]}]). > > Process One get 1 AND Process Two get 1, with the same key, of course!? > > > Is this correct? > No, that does not seem right. The table traversals done by ets:select* and ets:match* functions are not atomic, but the operation done on each found object should be atomic. That is, if you do ets:insert(T,{Key}) once and then several ets:select_delete(T, [{{Key},[],[true]}]) in parallel, only of of them should find {Key} and delete it. What OTP version is this? /Sverker From okaprinarjaya@REDACTED Mon Aug 12 17:38:08 2019 From: okaprinarjaya@REDACTED (I Gusti Ngurah Oka Prinarjaya) Date: Mon, 12 Aug 2019 22:38:08 +0700 Subject: [erlang-questions] More benefit and practical example of distributed Erlang/OTP (simple) application Message-ID: Hi, Again, my questions and confusions will base on Learn-You-Some-Erlang book. Yes, because i learn erlang from that book. And..thank you so much, Fred. Now, i just finished read and practicing https://learnyousomeerlang.com/distributed-otp-applications part of the book. From this part, i learn how to develop a super simple distributed app that runs in 3 separated nodes. I have web service infrastructure experience. I've done several freelance projects related to improving availability and delivery speed. Mostly done by clustering web servers, database servers, distributing traffic to clustered web servers, routing write and read to clustered databases servers, etc. My tools such as NginX, MariaDB Galera, MariaDB MaxScale, HAProxy, etc. If i try to compare what i learn in https://learnyousomeerlang.com/distributed-otp-applications with my experiences, i can't see the benefits of distributed erlang/otp app that explained in the book. Then my questions are: 1. Based on the book, i can't see the benefits by creating 2 backup nodes. Because there's no traffic distribution. Having 3 web-server machines then distributing traffic to them is more make sense for me for now. If 1 web-server failure, there's still 2 web-server left to serve. 2. Based on the book, service/module can execute at any nodes, but the service originally at the main / 1st node as long as the 1st node still alive. Service executed at 1st node. I can't see the benefits. Because in the end, it will only burden the 1st node. So what is the other 2 backup node is for? only act as a forwarder? The other 2 backup nodes are just "sitting", passive, doing nothing (except forwarding request) waiting for the 1st node to die. 3. I do really need to understand Erlang distributed programming, is there any more practical *simple* example? Yes, simple example, because if you ask me to read RabbitMQ's source code, that will make me drunk hahaha ?? Please enlightenment Thank you -------------- next part -------------- An HTML attachment was scrubbed... URL: From oliver.bollmann@REDACTED Mon Aug 12 17:59:41 2019 From: oliver.bollmann@REDACTED (Oliver Bollmann) Date: Mon, 12 Aug 2019 17:59:41 +0200 Subject: [erlang-questions] ets:select_delete not atomic? In-Reply-To: <1565620424.11130.11.camel@erlang.org> References: <1565620424.11130.11.camel@erlang.org> Message-ID: <97e804be-37d9-43e9-2931-12cd884136b5@t-online.de> Your are right, everything is ok! A simple example of key pool without gen_servers call, thanks to ets:select_delete!! -module(key_pool). %% API -export([new/1, in/2, in_new/2, out/1, out_compare/1, clear/1]). -spec(new(atom()) -> {ok,atom() | {already_exists,atom()}}). new(Pool)when is_atom(Pool) -> case ets:info(Pool,name)of undefined -> {ok,ets:new(Pool, [ordered_set,named_table,public, {write_concurrency,true},{read_concurrency,true}])}; Pool -> {already_exists,Pool} end. -spec(in(atom(),{any(),any()}) -> true). in(Pool,{Key,Val}) -> ets:insert(Pool,{Key,Val}). -spec(in_new(atom(),{any(),any()}) -> boolean()). in_new(Pool,{Key,Val}) -> ets:insert_new(Pool,{Key,Val}). -spec(out(atom()) -> {ok,{any(),any()} | empty}). out(Pool) -> case ets:select(Pool,[{'_',[],['$_']}],1)of {[{Key,_} =Item],_} -> case ets:select_delete(Pool,[{{Key,'_'},[],[true]}])of 1 -> {ok,Item}; 0 -> % context switch receive after 0 -> out(Pool) end end; '$end_of_table' -> empty end. -spec(out_compare(atom()) -> {ok,{any(),any()} | empty}). out_compare(Pool) -> case ets:select(Pool,[{'_',[],['$_']}],1)of {[{Key,Val} =Item],_} -> case ets:select_delete(Pool,[{{Key,Val},[],[true]}])of 1 -> {ok,Item}; 0 -> % context switch receive after 0 -> out(Pool) end end; '$end_of_table' -> empty end. -spec(clear(atom()) -> true). clear(Pool) -> ets:delete_all_objects(Pool). Oliver On 12.08.19 16:33, Sverker Eriksson wrote: > On m?n, 2019-08-12 at 14:16 +0200, Oliver Bollmann wrote: >> Hi, >> >> EtsName = ets:new(test,[named_table,ordered_set]), >> Res = ets:select_delete(EtsName,[{{Key},[],[true]}]). >> >> Res should be 1 or 0! >> >> But if i do this with a lot of process, at the same time, >> it happend that two process get 1! >> >> Start with: ets:insert(EtsName,{Key}). >> >> Process One: ets:select_delete(EtsName,[{{Key},[],[true]}]). >> Process Two: ets:select_delete(EtsName,[{{Key},[],[true]}]). >> >> Process One get 1 AND Process Two get 1, with the same key, of course! >> >> >> Is this correct? >> > No, that does not seem right. > > The table traversals done by ets:select* and ets:match* functions are not > atomic, but the operation done on each found object should be atomic. > > That is, if you do ets:insert(T,{Key}) once and then several > ets:select_delete(T, [{{Key},[],[true]}]) in parallel, only of of them should > find {Key} and delete it. > > What OTP version is this? > > /Sverker > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions -- Gr??e Oliver Bollmann -------------- next part -------------- An HTML attachment was scrubbed... URL: From t@REDACTED Mon Aug 12 17:59:25 2019 From: t@REDACTED (Tristan Sloughter) Date: Mon, 12 Aug 2019 09:59:25 -0600 Subject: [erlang-questions] =?utf-8?q?More_benefit_and_practical_example_o?= =?utf-8?q?f=09distributed_Erlang/OTP_=28simple=29_application?= In-Reply-To: References: Message-ID: <6b454d05-b839-4df9-817f-1bd44e72aaf3@www.fastmail.com> > If i try to compare what i learn in https://learnyousomeerlang.com/distributed-otp-applications with my experiences, i can't see the benefits of distributed erlang/otp app that explained in the book. And you are probably right. There is an important note in that chapter: > *Note:* In terms of distributed programming fallacies, distributed OTP applications assume that when there is a failure, it is likely due to a hardware failure, and not a netsplit. If you deem netsplits more likely than hardware failures, then you have to be aware of the possibility that the application is running both as a backup and main one, and that funny things could happen when the network issue is resolved. Maybe distributed OTP applications aren't the right mechanism for you in these cases. If you have a service that, for whatever reason (like not being a stateless service), you only can have 1 instance active at a time but you have additional nodes you can use as backups in case of hardware failure on the current active node then distributed applications are an answer. Tristan -------------- next part -------------- An HTML attachment was scrubbed... URL: From dszoboszlay@REDACTED Mon Aug 12 23:57:58 2019 From: dszoboszlay@REDACTED (=?UTF-8?Q?D=C3=A1niel_Szoboszlay?=) Date: Mon, 12 Aug 2019 23:57:58 +0200 Subject: [erlang-questions] More benefit and practical example of distributed Erlang/OTP (simple) application In-Reply-To: References: Message-ID: Let me try to give you a simple example to illustrate the use of distributed applications. Let's say you have a website and you want it to serve with a cluster of N nodes. You need a web server application, and that should be really running on all the nodes (so it's not an OTP distributed application), so all of the nodes will be utilised. But you also have an application that sends out a daily newsletter of top articles or whatever to your users. It is not a good idea to start this application on all the N nodes independently, because each of them would independently send out the same email, so your users would get N copies of that. Sending the newsletter is a task that should be done on exactly one node in the cluster (but it doesn't matter on which one): this is the use case for distributed applications. It's not about distributing load across nodes, it is for electing a single node in a distributed system to perform some task that has to be performed only once. But to be honest I wouldn't really recommend using distributed applications. They are very rarely used, and their implementation is not very robust. Practically, never try to have more than one distributed application in your release. (For those interested in the technical details: the dist_ac processes across the cluster run a protocol to decide where to start a distributed application. They can only run the protocol for one application at a time, and all the nodes have to participate in the protocol, so until a decision is made, they cannot handle requests to start an other application. Now let's imagine you have two distributed applications in your release, A and B (started in this order). If the node running B crashes and gets restarted by heart, the dist_ac processes may deadlock, because the newly restarted node would start running the protocol for A first, while the rest of the cluster is still running the protocol for B which has to be restarted somewhere after the crash.) There are better solutions for selecting a single node (or process) for doing a task only once in a cluster, such as gproc or global registered names. Cheers, Daniel On Mon, 12 Aug 2019 at 17:38, I Gusti Ngurah Oka Prinarjaya < okaprinarjaya@REDACTED> wrote: > Hi, > > Again, my questions and confusions will base on Learn-You-Some-Erlang > book. Yes, because i learn erlang from that book. And..thank you so much, > Fred. > > Now, i just finished read and practicing > https://learnyousomeerlang.com/distributed-otp-applications part of the > book. From this part, i learn how to develop a super simple distributed app > that runs in 3 separated nodes. > > I have web service infrastructure experience. I've done several freelance > projects related to improving availability and delivery speed. Mostly done > by clustering web servers, database servers, distributing traffic to > clustered web servers, routing write and read to clustered databases > servers, etc. My tools such as NginX, MariaDB Galera, MariaDB MaxScale, > HAProxy, etc. > > If i try to compare what i learn in > https://learnyousomeerlang.com/distributed-otp-applications with my > experiences, i can't see the benefits of distributed erlang/otp app that > explained in the book. Then my questions are: > > 1. Based on the book, i can't see the benefits by creating 2 backup nodes. > Because there's no traffic distribution. Having 3 web-server machines then > distributing traffic to them is more make sense for me for now. If 1 > web-server failure, there's still 2 web-server left to serve. > > 2. Based on the book, service/module can execute at any nodes, but the > service originally at the main / 1st node as long as the 1st node still > alive. Service executed at 1st node. I can't see the benefits. Because in > the end, it will only burden the 1st node. So what is the other 2 backup > node is for? only act as a forwarder? The other 2 backup nodes are just > "sitting", passive, doing nothing (except forwarding request) waiting for > the 1st node to die. > > 3. I do really need to understand Erlang distributed programming, is there > any more practical *simple* example? Yes, simple example, because if you > ask me to read RabbitMQ's source code, that will make me drunk hahaha ?? > > Please enlightenment > > Thank you > > > > > > > > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From oliver.bollmann@REDACTED Tue Aug 13 15:34:17 2019 From: oliver.bollmann@REDACTED (Oliver Bollmann) Date: Tue, 13 Aug 2019 15:34:17 +0200 Subject: [erlang-questions] maps:first Message-ID: <84721a64-2c7f-28e6-b453-2b34f73aa35f@t-online.de> I often need maps:first(Map), is there plan for it? My current implementation is: first(Map) -> case maps:next(maps:iterator(Map))of {Key,Val,_} -> {Key,Val}; none -> none end. Create the iterator always a new map? -- Gr??e Oliver Bollmann -------------- next part -------------- An HTML attachment was scrubbed... URL: From lukas@REDACTED Tue Aug 13 15:41:12 2019 From: lukas@REDACTED (Lukas Larsson) Date: Tue, 13 Aug 2019 15:41:12 +0200 Subject: [erlang-questions] maps:first In-Reply-To: <84721a64-2c7f-28e6-b453-2b34f73aa35f@t-online.de> References: <84721a64-2c7f-28e6-b453-2b34f73aa35f@t-online.de> Message-ID: On Tue, Aug 13, 2019 at 3:34 PM Oliver Bollmann wrote: > I often need maps:first(Map), is there plan for it? > No, there is currently no plan for it, as I cannot think of a use case when it would be useful, but that might just be poor imagination on my part. What do you use maps:first for? > My current implementation is: > > first(Map) -> > case maps:next(maps:iterator(Map)) of {Key,Val,_} -> {Key,Val}; > none -> none > end. > > Create the iterator always a new map? > > -- > Gr??e > Oliver Bollmann > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From oliver.bollmann@REDACTED Tue Aug 13 20:18:22 2019 From: oliver.bollmann@REDACTED (Oliver Bollmann) Date: Tue, 13 Aug 2019 20:18:22 +0200 Subject: [erlang-questions] maps:first In-Reply-To: References: <84721a64-2c7f-28e6-b453-2b34f73aa35f@t-online.de> Message-ID: <4b87f331-d2f5-cafd-13b8-e725b483d74e@t-online.de> Hi, i guess *we* do all the same, 1) processes with propery Y, i have about 1-10 million processes 2) gen_server to manage these processes in maps,dict,lists for example a pool with in,out,leave,delete 3) monitoring these processes Dilemma: If process P died i have to delete it from data structure using in 2) - maps, dict very fast; ?? lists -> List -- [Item] slow! ?? OK, i could use a sorted list and and the subtract would be faster, but insert is then slower! ?? And subtract need an algorithm! - i do not want a special process, only one random or the first one from data structure using in 2) ?? here is the place where i need *first_from_data_structure* **lists very fast: first defines it itself -> [First|Rest] = List, ?? but using maps or dict there is not first, at all! The question is: How can i get a random or first item from maps or dict? Hope that helps! Oliver On 13.08.19 15:41, Lukas Larsson wrote: > > > On Tue, Aug 13, 2019 at 3:34 PM Oliver Bollmann > > wrote: > > I often need maps:first(Map), is there plan for it? > > > No, there is currently no plan for it, as I cannot think of a use case > when it would be useful, but that might just be poor imagination on my > part. > > What do you use maps:first for? > > My current implementation is: > > first(Map) -> > case maps:next(maps:iterator(Map))of {Key,Val,_} -> {Key,Val}; > none -> none > end. Create the iterator always a new map? > > -- > Gr??e > Oliver Bollmann > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -- Gr??e Oliver Bollmann -------------- next part -------------- An HTML attachment was scrubbed... URL: From dmkolesnikov@REDACTED Tue Aug 13 21:24:37 2019 From: dmkolesnikov@REDACTED (dmkolesnikov@REDACTED) Date: Tue, 13 Aug 2019 22:24:37 +0300 Subject: [erlang-questions] maps:first In-Reply-To: <4b87f331-d2f5-cafd-13b8-e725b483d74e@t-online.de> References: <84721a64-2c7f-28e6-b453-2b34f73aa35f@t-online.de> <4b87f331-d2f5-cafd-13b8-e725b483d74e@t-online.de> Message-ID: Hello, May be my comment is not extremely relevant to this discussion but I would wish that Erlang data structures supports zipper trait. It make easy to iterate them back and force. Dmitry > On 13 Aug 2019, at 21.18, Oliver Bollmann wrote: > > Hi, > > i guess we do all the same, > > 1) processes with propery Y, i have about 1-10 million processes > 2) gen_server to manage these processes in maps,dict,lists for example a pool with in,out,leave,delete > 3) monitoring these processes > > Dilemma: > > If process P died i have to delete it from data structure using in 2) > > - maps, dict very fast; > lists -> List -- [Item] slow! > OK, i could use a sorted list and and the subtract would be faster, but insert is then slower! > And subtract need an algorithm! > > - i do not want a special process, only one random or the first one from data structure using in 2) > here is the place where i need first_from_data_structure > lists very fast: first defines it itself -> [First|Rest] = List, > but using maps or dict there is not first, at all! > > The question is: How can i get a random or first item from maps or dict? > > Hope that helps! > > Oliver > > > >> On 13.08.19 15:41, Lukas Larsson wrote: >> >> >>> On Tue, Aug 13, 2019 at 3:34 PM Oliver Bollmann wrote: >>> I often need maps:first(Map), is there plan for it? >>> >> >> No, there is currently no plan for it, as I cannot think of a use case when it would be useful, but that might just be poor imagination on my part. >> >> What do you use maps:first for? >> >>> My current implementation is: >>> >>> first(Map) -> >>> case maps:next(maps:iterator(Map)) of >>> {Key,Val,_} -> {Key,Val}; >>> none -> none >>> end. >>> >>> Create the iterator always a new map? >>> -- >>> Gr??e >>> Oliver Bollmann >>> _______________________________________________ >>> erlang-questions mailing list >>> erlang-questions@REDACTED >>> http://erlang.org/mailman/listinfo/erlang-questions > -- > Gr??e > Oliver Bollmann > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions -------------- next part -------------- An HTML attachment was scrubbed... URL: From g@REDACTED Wed Aug 14 00:10:05 2019 From: g@REDACTED (Guilherme Andrade) Date: Tue, 13 Aug 2019 23:10:05 +0100 Subject: [erlang-questions] maps:first In-Reply-To: <4b87f331-d2f5-cafd-13b8-e725b483d74e@t-online.de> References: <84721a64-2c7f-28e6-b453-2b34f73aa35f@t-online.de> <4b87f331-d2f5-cafd-13b8-e725b483d74e@t-online.de> Message-ID: On Tue, 13 Aug 2019 at 19:18, Oliver Bollmann wrote: > Hi, > > i guess *we* do all the same, > > 1) processes with propery Y, i have about 1-10 million processes > 2) gen_server to manage these processes in maps,dict,lists for example a > pool with in,out,leave,delete > 3) monitoring these processes > > Dilemma: > > If process P died i have to delete it from data structure using in 2) > > - maps, dict very fast; > lists -> List -- [Item] slow! > OK, i could use a sorted list and and the subtract would be faster, but > insert is then slower! > And subtract need an algorithm! > > - i do not want a special process, only one random or the first one from > data structure using in 2) > here is the place where i need *first_from_data_structure* > lists very fast: first defines it itself -> [First|Rest] = List, > but using maps or dict there is not first, at all! > Have you considered gb_trees[1]? Sure, for common use cases or large (enough) data sets they're slower than maps, but they're pretty fast notwithstanding, especially if your key types are cheap to compare. And since it's an ordered data type, you can then simply take the smallest pair when implementing those sort of melded-pool-and-monitor patterns. [1]: http://erlang.org/doc/man/gb_trees.html > The question is: How can i get a random or first item from maps or dict? > > Hope that helps! > > Oliver > > > On 13.08.19 15:41, Lukas Larsson wrote: > > > > On Tue, Aug 13, 2019 at 3:34 PM Oliver Bollmann < > oliver.bollmann@REDACTED> wrote: > >> I often need maps:first(Map), is there plan for it? >> > > No, there is currently no plan for it, as I cannot think of a use case > when it would be useful, but that might just be poor imagination on my part. > > What do you use maps:first for? > > >> My current implementation is: >> >> first(Map) -> >> case maps:next(maps:iterator(Map)) of {Key,Val,_} -> {Key,Val}; >> none -> none >> end. >> >> Create the iterator always a new map? >> >> -- >> Gr??e >> Oliver Bollmann >> >> _______________________________________________ >> erlang-questions mailing list >> erlang-questions@REDACTED >> http://erlang.org/mailman/listinfo/erlang-questions >> > -- > Gr??e > Oliver Bollmann > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -- Guilherme -------------- next part -------------- An HTML attachment was scrubbed... URL: From andreas.schultz@REDACTED Wed Aug 14 09:51:45 2019 From: andreas.schultz@REDACTED (Andreas Schultz) Date: Wed, 14 Aug 2019 09:51:45 +0200 Subject: [erlang-questions] maps:first In-Reply-To: <4b87f331-d2f5-cafd-13b8-e725b483d74e@t-online.de> References: <84721a64-2c7f-28e6-b453-2b34f73aa35f@t-online.de> <4b87f331-d2f5-cafd-13b8-e725b483d74e@t-online.de> Message-ID: Am Di., 13. Aug. 2019 um 20:18 Uhr schrieb Oliver Bollmann < oliver.bollmann@REDACTED>: > Hi, > > i guess *we* do all the same, > > 1) processes with propery Y, i have about 1-10 million processes > 2) gen_server to manage these processes in maps,dict,lists for example a > pool with in,out,leave,delete > 3) monitoring these processes > > Dilemma: > > If process P died i have to delete it from data structure using in 2) > > - maps, dict very fast; > lists -> List -- [Item] slow! > OK, i could use a sorted list and and the subtract would be faster, but > insert is then slower! > And subtract need an algorithm! > > - i do not want a special process, only one random or the first one from > data structure using in 2) > here is the place where i need *first_from_data_structure* > lists very fast: first defines it itself -> [First|Rest] = List, > but using maps or dict there is not first, at all! > Are you sure a maps first is really what you want? Maps leys are not ordered (beyond MAP_SMALL_MAP_LIMIT, which is 32), but they are also not random. As long as your map has less elements than MAP_SMALL_MAP_LIMIT it will behave like a ordered list, beyond that it will use a hash for ordering. That means that for a given set of keys the ordering will be stable (but not sorted). So when you take the first element of a map and put it back again (based on key), it will be the new first element again. IMHO the only use case for you maps:first function is something that tries to distribute new requests/elements across the elements of a map. Your maps:first function coupled with the constant ordering of map keys would lead to a distribution that is highly skewed towards a small number of keys (or even just one key). Now, a maps:nth/2 function that works like list:nth/2 is another story. You could use maps:nth(rand:uniform(maps:size(Map)), Map) to get a somewhat evenly distributed key/element from a map. Implementing this function currently requires you to convert the map to a list first. For large maps having a maps:nth/2 should yield better performance. Regards Andreas The question is: How can i get a random or first item from maps or dict? > > Hope that helps! > > Oliver > > > On 13.08.19 15:41, Lukas Larsson wrote: > > > > On Tue, Aug 13, 2019 at 3:34 PM Oliver Bollmann < > oliver.bollmann@REDACTED> wrote: > >> I often need maps:first(Map), is there plan for it? >> > > No, there is currently no plan for it, as I cannot think of a use case > when it would be useful, but that might just be poor imagination on my part. > > What do you use maps:first for? > > >> My current implementation is: >> >> first(Map) -> >> case maps:next(maps:iterator(Map)) of {Key,Val,_} -> {Key,Val}; >> none -> none >> end. >> >> Create the iterator always a new map? >> >> -- >> Gr??e >> Oliver Bollmann >> >> _______________________________________________ >> erlang-questions mailing list >> erlang-questions@REDACTED >> http://erlang.org/mailman/listinfo/erlang-questions >> > -- > Gr??e > Oliver Bollmann > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -- Andreas Schultz -- Principal Engineer t: +49 391 819099-224 ------------------------------- enabling your networks ----------------------------- Travelping GmbH Roentgenstra?e 13 39108 Magdeburg Germany t: +49 391 819099-0 f: +49 391 819099-299 e: info@REDACTED w: https://www.travelping.com/ Company registration: Amtsgericht Stendal Reg. No.: HRB 10578 Geschaeftsfuehrer: Holger Winkelmann VAT ID: DE236673780 -------------- next part -------------- An HTML attachment was scrubbed... URL: From micaelnussbaumer@REDACTED Thu Aug 15 13:33:03 2019 From: micaelnussbaumer@REDACTED (Micael Nussbaumer) Date: Thu, 15 Aug 2019 12:33:03 +0100 Subject: [erlang-questions] Testing gen_statem timers Message-ID: Hi, first time poster (but I've read many threads in here). How does one usually test gen_statem internal timer events? Usually you test the effects of the behaviour somehow, and I can test that. But in this particular case I had a situation where timers with uniq references are created, later on they usually get removed and all is fine - they're created for each extra worker started and at some point the worker is removed by the timer event that trigger checking some conditions. I noticed after that, the way I had written it, if an extra worker was started then died for some other reason than the timer event taking it out, I could theoretically accumulate timers that wouldn't be removed, I've since then corrected that but still I have no tests ensuring me that it actually works. So my question is if there's any even way to test it (even if with tracing)? Thanks *M*icael *N*ussbaumer artistic portfolio -------------- next part -------------- An HTML attachment was scrubbed... URL: From wallentin.dahlberg@REDACTED Thu Aug 15 14:12:46 2019 From: wallentin.dahlberg@REDACTED (=?UTF-8?Q?Bj=C3=B6rn=2DEgil_Dahlberg?=) Date: Thu, 15 Aug 2019 14:12:46 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: <20190805114524.GA5959@erix.ericsson.se> References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> <20190805072937.GA64211@erix.ericsson.se> <32a6fec8-49e7-4770-52b6-7887f7ae229a@hedeland.org> <547DFD68-A005-4C1E-8039-88A315F0F8C5@micic.co.za> <9ffac6d6-5e95-d70d-c1bb-9a95e755dccc@hedeland.org> <20190805114524.GA5959@erix.ericsson.se> Message-ID: Den m?n 5 aug. 2019 kl 13:45 skrev Raimo Niskanen < raimo+erlang-questions@REDACTED>: > > > > But maybe it's "just" something that was a challenge to implement, and > > will be fixed to match the current documentation in a future release... > > I think it is precisely like that. It is documented as it was intended, > but implementing it was a challenge so it got only partly implemented. > (constructing a new term for map lookup in the context of a pattern match > proved an unexpectedly hard problem, I guess) > IIRC the case that was troublesome was the failure case, say K = a case Map of #{ K + 1 := V } -> V; ... Meaning it is essentially no trouble to evaluate the key expression before the case expression, however the semantics for what should happen if the key expression fails were never really defined. The easy option it just to throw an exception and that makes some sort of sense, but it could make more sense that we say "the pattern does not match" and then test the next clause in the case expression. This latter option is also a bit harder to implement ofc. The core and kernel language does not really expect this behaviour :) go and figure ^^ In other words - it is not implemented because we, well I, missed this case when defining the semantics. My bad. Bj?rn-Egil > > So it is a known limitation, to us that know it ;-) > unfortunately not nicely documented, > and the goal is to fix it some day... > > http://erlang.org/pipermail/erlang-questions/2016-May/089269.html > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From per@REDACTED Thu Aug 15 15:05:44 2019 From: per@REDACTED (Per Hedeland) Date: Thu, 15 Aug 2019 15:05:44 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> <20190805072937.GA64211@erix.ericsson.se> <32a6fec8-49e7-4770-52b6-7887f7ae229a@hedeland.org> <547DFD68-A005-4C1E-8039-88A315F0F8C5@micic.co.za> <9ffac6d6-5e95-d70d-c1bb-9a95e755dccc@hedeland.org> <20190805114524.GA5959@erix.ericsson.se> Message-ID: <56ca15ae-bacd-cfad-fee1-86db9df15c32@hedeland.org> On 2019-08-15 14:12, Bj?rn-Egil Dahlberg wrote: > Den m?n 5 aug. 2019 kl 13:45 skrev Raimo Niskanen >: > > > > > But maybe it's "just" something that was a challenge to implement, and > > will be fixed to match the current documentation in a future release... > > I think it is precisely like that. It is documented as it was intended, > but implementing it was a challenge so it got only partly implemented. > (constructing a new term for map lookup in the context of a pattern match > proved an unexpectedly hard problem, I guess) > > > IIRC the case that was troublesome was the failure case, say > > K = a > > case Map of > #{ K + 1 := V } -> V; > ... > > Meaning it is essentially no trouble to evaluate the key expression before the case expression, however the semantics for what should happen if the key expression fails were never really defined. Hm, is this really different from other expressions in a pattern? 1> K = a. a 2> Map = b. b 3> case Map of K + 1 -> true; _ -> false end. * 1: illegal pattern Which is because An arithmetic expression can be used within a pattern if it meets both of the following two conditions: o It uses only numeric or bitwise operators. o Its value can be evaluated to a constant when complied. I.e. it seems to me that this restriction (and compile-time error) "should just apply" also to map keys in patterns - it's still "an aritmetic expression within a pattern". Are there other failure cases, that would cause problems for expressions that don't violate this restriction? --Per > The easy option it just to throw an exception and that makes some sort of sense, but it could make more sense that we say "the pattern does not match" and then test the next clause in the case > expression. This latter option is also a bit harder to implement ofc. The core and kernel language does not really expect this behaviour :) go and figure ^^ > > In other words - it is not implemented because we, well I, missed this case when defining the semantics. > > My bad. > Bj?rn-Egil > > > So it is a known limitation, to us that know it ;-) > unfortunately not nicely documented, > and the goal is to fix it some day... > > http://erlang.org/pipermail/erlang-questions/2016-May/089269.html > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > From raimo+erlang-questions@REDACTED Thu Aug 15 15:45:39 2019 From: raimo+erlang-questions@REDACTED (Raimo Niskanen) Date: Thu, 15 Aug 2019 15:45:39 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: Message-ID: <20190815134539.GA1274@erix.ericsson.se> On Thu, Aug 15, 2019 at 12:33:03PM +0100, Micael Nussbaumer wrote: > Hi, first time poster (but I've read many threads in here). > > How does one usually test gen_statem internal timer events? > Usually you test the effects of the behaviour somehow, and I can test that. > But in this particular case I had a situation where timers with uniq > references are created, later on they usually get removed and all is fine - > they're created for each extra worker started and at some point the worker > is removed by the timer event that trigger checking some conditions. > > I noticed after that, the way I had written it, if an extra worker was > started then died for some other reason than the timer event taking it out, > I could theoretically accumulate timers that wouldn't be removed, I've > since then corrected that but still I have no tests ensuring me that it > actually works. > So my question is if there's any even way to test it (even if with tracing)? > Thanks For the current code on maint and master (I think): If you trace gen_statem:loop/3; the third argument is a #state{} record whose 3:rd field (3:rd record field - 4:th tuple field) are the timers. The timers is a 2-tuple with two maps; one Ref => Name and one Name => Ref. You might observe these maps and verify that they do not grow. It should be possible to write a trace match spec that filters out and only delivers this field to the tracer. > > *M*icael *N*ussbaumer > artistic portfolio -- / Raimo Niskanen, Erlang/OTP, Ericsson AB From dszoboszlay@REDACTED Thu Aug 15 15:50:47 2019 From: dszoboszlay@REDACTED (=?UTF-8?Q?D=C3=A1niel_Szoboszlay?=) Date: Thu, 15 Aug 2019 15:50:47 +0200 Subject: [erlang-questions] Illegal map key in pattern In-Reply-To: <56ca15ae-bacd-cfad-fee1-86db9df15c32@hedeland.org> References: <82953A05-DC0F-4FAE-AE36-C24E70A21BA7@micic.co.za> <20190805072937.GA64211@erix.ericsson.se> <32a6fec8-49e7-4770-52b6-7887f7ae229a@hedeland.org> <547DFD68-A005-4C1E-8039-88A315F0F8C5@micic.co.za> <9ffac6d6-5e95-d70d-c1bb-9a95e755dccc@hedeland.org> <20190805114524.GA5959@erix.ericsson.se> <56ca15ae-bacd-cfad-fee1-86db9df15c32@hedeland.org> Message-ID: So the documentation currently says: Matching of key-value associations from maps is done as follows: > #{ K := V } = M Here M is any map. The key K must be an expression with bound variables or > literals. V can be any pattern with either bound or unbound variables. I think the problem with it is that the key should be a *pattern* with bound variables, not an *expression*. Since #{K := V} is clearly a pattern, it doesn't make sense to allow a part of it to be an expression (which is a more generic thing than a pattern). At least I wouldn't expect #{httpc:request("https://google.com/") := V} to be a valid pattern, while httpc:request("https://google.com/") *is* an expression with bound variables or literals. But I would expect all patterns listed in http://erlang.org/doc/reference_manual/expressions.html#patterns that contain only bounded variables or literals to be usable as K. This would include things like: #{[X|Y] := Z} % assuming X and Y are bounded #{1 + 2 := A} #{"foo" ++ X := Y} % assuming X is bounded This would make sense because the following patterns work just fine: {[X|Y], Z} {1 + 2, A} {"foo" ++ X, Y} By the way, one question that would still remain open is whether Erlang shall allow operator = in key patterns: #{(X = {foo, bar}) := Y} Because {(X = {foo, bar}), Y} is a valid pattern, regardless of X being bound or not. But this seems to be a lot less important issue. Cheers, Daniel On Thu, 15 Aug 2019 at 15:06, Per Hedeland wrote: > On 2019-08-15 14:12, Bj?rn-Egil Dahlberg wrote: > > Den m?n 5 aug. 2019 kl 13:45 skrev Raimo Niskanen < > raimo+erlang-questions@REDACTED raimo%2Berlang-questions@REDACTED>>: > > > > > > > > But maybe it's "just" something that was a challenge to > implement, and > > > will be fixed to match the current documentation in a future > release... > > > > I think it is precisely like that. It is documented as it was > intended, > > but implementing it was a challenge so it got only partly > implemented. > > (constructing a new term for map lookup in the context of a pattern > match > > proved an unexpectedly hard problem, I guess) > > > > > > IIRC the case that was troublesome was the failure case, say > > > > K = a > > > > case Map of > > #{ K + 1 := V } -> V; > > ... > > > > Meaning it is essentially no trouble to evaluate the key expression > before the case expression, however the semantics for what should happen if > the key expression fails were never really defined. > > Hm, is this really different from other expressions in a pattern? > > 1> K = a. > a > 2> Map = b. > b > 3> case Map of K + 1 -> true; _ -> false end. > * 1: illegal pattern > > Which is because > > An arithmetic expression can be used within a pattern if it meets > both of the following two conditions: > > o It uses only numeric or bitwise operators. > o Its value can be evaluated to a constant when complied. > > I.e. it seems to me that this restriction (and compile-time error) > "should just apply" also to map keys in patterns - it's still "an > aritmetic expression within a pattern". Are there other failure cases, > that would cause problems for expressions that don't violate this > restriction? > > --Per > > > The easy option it just to throw an exception and that makes some sort > of sense, but it could make more sense that we say "the pattern does not > match" and then test the next clause in the case > > expression. This latter option is also a bit harder to implement ofc. > The core and kernel language does not really expect this behaviour :) go > and figure ^^ > > > > In other words - it is not implemented because we, well I, missed this > case when defining the semantics. > > > > My bad. > > Bj?rn-Egil > > > > > > So it is a known limitation, to us that know it ;-) > > unfortunately not nicely documented, > > and the goal is to fix it some day... > > > > http://erlang.org/pipermail/erlang-questions/2016-May/089269.html > > > > > > _______________________________________________ > > erlang-questions mailing list > > erlang-questions@REDACTED > > http://erlang.org/mailman/listinfo/erlang-questions > > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From torben.lehoff@REDACTED Thu Aug 15 18:44:43 2019 From: torben.lehoff@REDACTED (Torben Hoffmann) Date: Thu, 15 Aug 2019 18:44:43 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: Message-ID: Hi Micael, I'm very biassed here, but apart from my creator fondness many of my colleagues are very happy about the approach that my Chronos library takes when it comes to timers. https://github.com/lehoff/chronos Basically, don't use the internal timers, but do read the full README from Chronos. Very happy to assist you and improve anything in Chronos, if you find it confusing. Cheers, Torben On Thu, 15 Aug 2019 at 13:35, Micael Nussbaumer wrote: > Hi, first time poster (but I've read many threads in here). > > How does one usually test gen_statem internal timer events? > Usually you test the effects of the behaviour somehow, and I can test > that. But in this particular case I had a situation where timers with uniq > references are created, later on they usually get removed and all is fine - > they're created for each extra worker started and at some point the worker > is removed by the timer event that trigger checking some conditions. > > I noticed after that, the way I had written it, if an extra worker was > started then died for some other reason than the timer event taking it out, > I could theoretically accumulate timers that wouldn't be removed, I've > since then corrected that but still I have no tests ensuring me that it > actually works. > So my question is if there's any even way to test it (even if with > tracing)? > Thanks > > *M*icael *N*ussbaumer > artistic portfolio > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -- http://www.linkedin.com/in/torbenhoffmann @LeHoff -------------- next part -------------- An HTML attachment was scrubbed... URL: From roger@REDACTED Thu Aug 15 19:16:10 2019 From: roger@REDACTED (Roger Lipscombe) Date: Thu, 15 Aug 2019 18:16:10 +0100 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: Message-ID: I'm not convinced that this is how I'd do it these days, but I dug through some of our existing unit tests and found some code that uses dbg:tpl(erlang, send_after, ...), etc. to track whether a process has pending timers. I yoinked it out of our source tree and stuck it in a gist: https://gist.github.com/rlipscombe/a0970b147b35cfea6330533431e3de4c On Thu, 15 Aug 2019 at 12:35, Micael Nussbaumer wrote: > > Hi, first time poster (but I've read many threads in here). > > How does one usually test gen_statem internal timer events? > Usually you test the effects of the behaviour somehow, and I can test that. But in this particular case I had a situation where timers with uniq references are created, later on they usually get removed and all is fine - they're created for each extra worker started and at some point the worker is removed by the timer event that trigger checking some conditions. > > I noticed after that, the way I had written it, if an extra worker was started then died for some other reason than the timer event taking it out, I could theoretically accumulate timers that wouldn't be removed, I've since then corrected that but still I have no tests ensuring me that it actually works. > So my question is if there's any even way to test it (even if with tracing)? > Thanks > > Micael Nussbaumer > artistic portfolio > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions From raimo+erlang-questions@REDACTED Fri Aug 16 10:43:43 2019 From: raimo+erlang-questions@REDACTED (Raimo Niskanen) Date: Fri, 16 Aug 2019 10:43:43 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: Message-ID: <20190816084343.GA43696@erix.ericsson.se> On Thu, Aug 15, 2019 at 06:44:43PM +0200, Torben Hoffmann wrote: > Hi Micael, > > I'm very biassed here, but apart from my creator fondness many of my > colleagues are very happy about the approach that my Chronos library takes > when it comes to timers. > > https://github.com/lehoff/chronos I notice that in that README.md you compare Chronos with the timeout feature in gen_server and gen_fsm. The timers in gen_statem were specifically designed to remedy most of their shortcomings. So, from a usability point of view, can you elaborate what Cronos can do better than gen_statem timers? > > Basically, don't use the internal timers, but do read the full README from > Chronos. > > Very happy to assist you and improve anything in Chronos, if you find it > confusing. > > Cheers, > Torben > > On Thu, 15 Aug 2019 at 13:35, Micael Nussbaumer > wrote: > > > Hi, first time poster (but I've read many threads in here). > > > > How does one usually test gen_statem internal timer events? > > Usually you test the effects of the behaviour somehow, and I can test > > that. But in this particular case I had a situation where timers with uniq > > references are created, later on they usually get removed and all is fine - > > they're created for each extra worker started and at some point the worker > > is removed by the timer event that trigger checking some conditions. > > > > I noticed after that, the way I had written it, if an extra worker was > > started then died for some other reason than the timer event taking it out, > > I could theoretically accumulate timers that wouldn't be removed, I've > > since then corrected that but still I have no tests ensuring me that it > > actually works. > > So my question is if there's any even way to test it (even if with > > tracing)? > > Thanks > > > > *M*icael *N*ussbaumer > > artistic portfolio > > > > > -- > http://www.linkedin.com/in/torbenhoffmann > @LeHoff -- / Raimo Niskanen, Erlang/OTP, Ericsson AB From raimo+erlang-questions@REDACTED Fri Aug 16 10:46:49 2019 From: raimo+erlang-questions@REDACTED (Raimo Niskanen) Date: Fri, 16 Aug 2019 10:46:49 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: Message-ID: <20190816084649.GB43696@erix.ericsson.se> Might timer logging / status be a desirable missing debug feature for gen_statem? / Raimo On Thu, Aug 15, 2019 at 12:33:03PM +0100, Micael Nussbaumer wrote: > Hi, first time poster (but I've read many threads in here). > > How does one usually test gen_statem internal timer events? > Usually you test the effects of the behaviour somehow, and I can test that. > But in this particular case I had a situation where timers with uniq > references are created, later on they usually get removed and all is fine - > they're created for each extra worker started and at some point the worker > is removed by the timer event that trigger checking some conditions. > > I noticed after that, the way I had written it, if an extra worker was > started then died for some other reason than the timer event taking it out, > I could theoretically accumulate timers that wouldn't be removed, I've > since then corrected that but still I have no tests ensuring me that it > actually works. > So my question is if there's any even way to test it (even if with tracing)? > Thanks > > *M*icael *N*ussbaumer > artistic portfolio > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions -- / Raimo Niskanen, Erlang/OTP, Ericsson AB From torben.lehoff@REDACTED Fri Aug 16 12:36:29 2019 From: torben.lehoff@REDACTED (Torben Hoffmann) Date: Fri, 16 Aug 2019 12:36:29 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: <20190816084343.GA43696@erix.ericsson.se> References: <20190816084343.GA43696@erix.ericsson.se> Message-ID: On Fri, 16 Aug 2019 at 10:43, Raimo Niskanen < raimo+erlang-questions@REDACTED> wrote: > On Thu, Aug 15, 2019 at 06:44:43PM +0200, Torben Hoffmann wrote: > > Hi Micael, > > > > I'm very biassed here, but apart from my creator fondness many of my > > colleagues are very happy about the approach that my Chronos library > takes > > when it comes to timers. > > > > https://github.com/lehoff/chronos > > I notice that in that README.md you compare Chronos with the timeout > feature > in gen_server and gen_fsm. The timers in gen_statem were specifically > designed to remedy most of their shortcomings. > > So, from a usability point of view, can you elaborate what Cronos > can do better than gen_statem timers? > > I have a todo to update the README.md to cover gen_statem as well - thanks for reminding me! I have worked a lot with gen_statem - absolutely a very good component and easy to work with. But the problem of mocking still remains the same. When testing I prefer to mock time so that I don't have to wait for the timeout to occur. Furthermore, I'm so heavily influenced by my ten years at Motorola that I want the timers to stand out as in all the nice SDL diagrams in the standards shows. That means that I want an easy way to check that a timer has been started (mock the call to chronos:start_timer()) and then an easy way to induce the expiry of said timer without having to wait for whatever the delay is. When you have timers in the minutes range you just don't want your automated tests to wait it out. If there is a way to avoid this with gen_statem I'd be most interested! Cheers, Torben > > > > Basically, don't use the internal timers, but do read the full README > from > > Chronos. > > > > Very happy to assist you and improve anything in Chronos, if you find it > > confusing. > > > > Cheers, > > Torben > > > > On Thu, 15 Aug 2019 at 13:35, Micael Nussbaumer < > micaelnussbaumer@REDACTED> > > wrote: > > > > > Hi, first time poster (but I've read many threads in here). > > > > > > How does one usually test gen_statem internal timer events? > > > Usually you test the effects of the behaviour somehow, and I can test > > > that. But in this particular case I had a situation where timers with > uniq > > > references are created, later on they usually get removed and all is > fine - > > > they're created for each extra worker started and at some point the > worker > > > is removed by the timer event that trigger checking some conditions. > > > > > > I noticed after that, the way I had written it, if an extra worker was > > > started then died for some other reason than the timer event taking it > out, > > > I could theoretically accumulate timers that wouldn't be removed, I've > > > since then corrected that but still I have no tests ensuring me that it > > > actually works. > > > So my question is if there's any even way to test it (even if with > > > tracing)? > > > Thanks > > > > > > *M*icael *N*ussbaumer > > > artistic portfolio > > > > > > > > > -- > > http://www.linkedin.com/in/torbenhoffmann > > @LeHoff > > > -- > > / Raimo Niskanen, Erlang/OTP, Ericsson AB > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -- http://www.linkedin.com/in/torbenhoffmann @LeHoff -------------- next part -------------- An HTML attachment was scrubbed... URL: From jesper.louis.andersen@REDACTED Fri Aug 16 13:06:21 2019 From: jesper.louis.andersen@REDACTED (Jesper Louis Andersen) Date: Fri, 16 Aug 2019 13:06:21 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: <20190816084343.GA43696@erix.ericsson.se> Message-ID: On Fri, Aug 16, 2019 at 12:36 PM Torben Hoffmann wrote: > When testing I prefer to mock time so that I don't have to wait for the > timeout to occur. > The key observation is this: You want time to be an injected parameter. First, note that there is no concept of "now". Any call to e.g., `erlang:monotonic_time()` is behind as soon as your code has that value, by a small epsilon. In many cases, it is late by a lot; several milliseconds. So it is better to have your code take a parameter which is a point in time. When this is received, you roll time forward to that point in your internal state. Second, timers are the scourge of testing. They are side-effects which means they are usually handled by mocking. And mocking is never the answer if there is a decent way around it. However, if a timer turns into a message, then we can choose to have timers handled outside the component and then send messages into the component. This helps testing, as we can run with a time-compression component, removing typical long waits in our test cases. In fact, separation of effects from computation is almost always a win for code in general. Third, in systems you want a clock that is stationary and only moves when you call `advance_time(Ms)` or something such. A clock which moves behind your back is just going to create a lot of havoc in your code and computation. So it is better to ignore the real physical world, and then use messaging to handle the advance of the clock. When I did some QuickCheck work, I built up a submodel which plays the role as the internal erlang timers. This means the model can simulate timers in the system and make choices as to when a timer fires, when time advances, what the interesting timestamps are, and so on. In particular, the order in which timers fire is nondeterministic. This is a mocking solution to the problem, and it required the code to be structured around being easy to hook. In QuickCheck tests, you must know in advance what is going to happen to the system-under-test. Perhaps a way to ask a component for its current timers, a way to disable the firing of timers and a way to inject a given timer back would give a tester the tooling for doing dynamic interaction, like most unit tests are doing. Also, I've been toying a bit with Janes St. Incremental implementation (In ocaml). They also have a stationary clock which can be advanced from the outside[0]. [0] Getting self-adjusting computations into Erlang is actually a hard problem. The implementation relies on being able to control the firing schedule of incremental nodes, something you cannot easily do in Erlang processes say. -------------- next part -------------- An HTML attachment was scrubbed... URL: From fchschneider@REDACTED Fri Aug 16 14:46:43 2019 From: fchschneider@REDACTED (Frans Schneider) Date: Fri, 16 Aug 2019 14:46:43 +0200 Subject: [erlang-questions] C Nodes and depreciated erl_Interface Message-ID: <2d73125f-fa13-2851-cae8-f1a35ce7522e@gmail.com> Hi list, I have to implement an interface between C and Erlang as a client C node. The C nodes chapter in the Interoperability Tutorial User's Guide [1] still uses the erl_interface library. which is depreciated. I was wondering if somebody knows about a similar tutorial / example using the ei library? Tkanks, Frans [1] http://erlang.org/doc/tutorial/cnode.html From vances@REDACTED Fri Aug 16 15:28:16 2019 From: vances@REDACTED (Vance Shipley) Date: Fri, 16 Aug 2019 21:28:16 +0800 Subject: [erlang-questions] C Nodes and depreciated erl_Interface In-Reply-To: <2d73125f-fa13-2851-cae8-f1a35ce7522e@gmail.com> References: <2d73125f-fa13-2851-cae8-f1a35ce7522e@gmail.com> Message-ID: On Fri, Aug 16, 2019 at 8:46 PM Frans Schneider wrote: > The C nodes chapter in the Interoperability Tutorial User's Guide > [1] still uses the erl_interface library. which is depreciated. I think you'll find it still applies: erl_eterm: erl_init() erl_connect: erl_connect_init() erl_connect_xinit() erl_connect() erl_publish() erl_accept() erl_receive_msg() erl_send() erl_eterm: erl_element() erl_format: erl_format() erl_malloc: erl_free_term() -- -Vance From mononcqc@REDACTED Fri Aug 16 15:40:08 2019 From: mononcqc@REDACTED (Fred Hebert) Date: Fri, 16 Aug 2019 09:40:08 -0400 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: <20190816084343.GA43696@erix.ericsson.se> Message-ID: On Fri, Aug 16, 2019 at 7:07 AM Jesper Louis Andersen < jesper.louis.andersen@REDACTED> wrote: > > Second, timers are the scourge of testing. They are side-effects which > means they are usually handled by mocking. And mocking is never the answer > if there is a decent way around it. However, if a timer turns into a > message, then we can choose to have timers handled outside the component > and then send messages into the component. This helps testing, as we can > run with a time-compression component, removing typical long waits in our > test cases. In fact, separation of effects from computation is almost > always a win for code in general. > > This has been my general go-to strategy, but note that this isn't really doable with a gen_statem since the timer events have their own type of message, which you cannot fake in a generic manner (the same way you would just do it with a timeout message in other behaviours). You at the very least need to add a special injection-creating callback that uses the next_event action to inject a timeout of the type you want, and the way -ifdefs work in Erlang, that clause can't optionally be compiled out for production. Other types of mocking or time handling otherwise need to be aware of implementation details in gen_statem to know which clocks to mock and advance. -------------- next part -------------- An HTML attachment was scrubbed... URL: From raimo+erlang-questions@REDACTED Fri Aug 16 15:47:20 2019 From: raimo+erlang-questions@REDACTED (Raimo Niskanen) Date: Fri, 16 Aug 2019 15:47:20 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: <20190816084343.GA43696@erix.ericsson.se> Message-ID: <20190816134720.GA77661@erix.ericsson.se> On Fri, Aug 16, 2019 at 12:36:29PM +0200, Torben Hoffmann wrote: > On Fri, 16 Aug 2019 at 10:43, Raimo Niskanen < > raimo+erlang-questions@REDACTED> wrote: > > > On Thu, Aug 15, 2019 at 06:44:43PM +0200, Torben Hoffmann wrote: > > > Hi Micael, > > > > > > I'm very biassed here, but apart from my creator fondness many of my > > > colleagues are very happy about the approach that my Chronos library > > takes > > > when it comes to timers. > > > > > > https://github.com/lehoff/chronos > > > > I notice that in that README.md you compare Chronos with the timeout > > feature > > in gen_server and gen_fsm. The timers in gen_statem were specifically > > designed to remedy most of their shortcomings. > > > > So, from a usability point of view, can you elaborate what Cronos > > can do better than gen_statem timers? > > > > I have a todo to update the README.md to cover gen_statem as well - thanks > for reminding me! Great! No problem ;-) > > I have worked a lot with gen_statem - absolutely a very good component and > easy to work with. Always nice to hear! :-) > But the problem of mocking still remains the same. > When testing I prefer to mock time so that I don't have to wait for the > timeout to occur. > Furthermore, I'm so heavily influenced by my ten years at Motorola that I > want the timers to stand out as in all the nice SDL diagrams in the > standards shows. > That means that I want an easy way to check that a timer has been started > (mock the call to chronos:start_timer()) and then an easy way to induce the > expiry of said timer without having to wait for whatever the delay is. > When you have timers in the minutes range you just don't want your > automated tests to wait it out. > > If there is a way to avoid this with gen_statem I'd be most interested! Not today. For debugging only, not mocking, it would be possible to log timer actions in the sys log, and to include timer statistics i.e the number of running timers or a list of them in sys:get_status/1. Would that be interesting fetures? For mocking, a possible new feature would be to make the calls to erlang:start_timer/4 and erlang:cancel_timer/1 pluggable, i.e call them through fun:s. Then the plugged in functions may for example communicate with a registered timer server that can do as it pleases about when to fire timeouts, log timer starts and cancels, etc... How dynamic would such a feature need to be? * An option to gen_statem:start{,_link}/3,4? * Read application variable at server start? * Return an action from the callback module (so the callback module can implement a function to activate mocking)? * Other suggestions? Interesting topic - I did not forsee this need... BRs / Raimo > > Cheers, > Torben > > > > > > > > Basically, don't use the internal timers, but do read the full README > > from > > > Chronos. > > > > > > Very happy to assist you and improve anything in Chronos, if you find it > > > confusing. > > > > > > Cheers, > > > Torben > > > > > > On Thu, 15 Aug 2019 at 13:35, Micael Nussbaumer < > > micaelnussbaumer@REDACTED> > > > wrote: > > > > > > > Hi, first time poster (but I've read many threads in here). > > > > > > > > How does one usually test gen_statem internal timer events? > > > > Usually you test the effects of the behaviour somehow, and I can test > > > > that. But in this particular case I had a situation where timers with > > uniq > > > > references are created, later on they usually get removed and all is > > fine - > > > > they're created for each extra worker started and at some point the > > worker > > > > is removed by the timer event that trigger checking some conditions. > > > > > > > > I noticed after that, the way I had written it, if an extra worker was > > > > started then died for some other reason than the timer event taking it > > out, > > > > I could theoretically accumulate timers that wouldn't be removed, I've > > > > since then corrected that but still I have no tests ensuring me that it > > > > actually works. > > > > So my question is if there's any even way to test it (even if with > > > > tracing)? > > > > Thanks > > > > > > > > *M*icael *N*ussbaumer > > > > artistic portfolio > > > > > > > > > > > > > -- > > > http://www.linkedin.com/in/torbenhoffmann > > > @LeHoff > > > > > > -- > > > > / Raimo Niskanen, Erlang/OTP, Ericsson AB > > _______________________________________________ > > erlang-questions mailing list > > erlang-questions@REDACTED > > http://erlang.org/mailman/listinfo/erlang-questions > > > > > -- > http://www.linkedin.com/in/torbenhoffmann > @LeHoff > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions -- / Raimo Niskanen, Erlang/OTP, Ericsson AB From otb@REDACTED Fri Aug 16 12:14:11 2019 From: otb@REDACTED (=?UTF-8?Q?S=c3=a9bastien_BRICE?=) Date: Fri, 16 Aug 2019 12:14:11 +0200 Subject: [erlang-questions] Handling routing_key for topic routing in gen_server handle_info Message-ID: <8004b4b4-8330-cc28-01a5-059688d1a102@opentelecom.fr> Hello there, I am a bit new to the Erlang Environment I am writing an emailtesting application that filters incoming email with a randomly generated routing_keys on a topic exchange to make emails entering my system Once they are delivered (and processed) on an queue, I want to label them again with the previously randomly routing_key to route them to another exchange to make them ready for the final consume. This 2nd producing step is causing me real troubles I am getting data back from a tcp socket (processed by a third-tier program: spamassassin) with handle_info pattern matching I rely on a gen_server to consume messages first through the regular amqp_client/include/amqp_client.hrl Library I use handle_info in my gen_server behaviour and then pattern match on the parameters. Detecting delivered AMQP message is done through function heads (records) in handle_info callback ***My gen_server**** handle_info({#'basic.deliver'{routing_key=Key, consumer_tag=Tag}, Content}, State) -> ??? #amqp_msg{props = Properties, payload = Payload} = Content, ??? #'P_basic'{message_id = MessageId, headers = Headers} = Properties, ??? send_to_spamassassin:calcule_score(Payload), ??? {noreply, State}; handle_info(Msg, State) -> ??? case Msg of ??????? {_,_,Data} -> ?????????? scored_email:main(Data); ??????? {_,_} -> ??? end, ??? {noreply, State}. ***send_to_spamassassin function *** ??? calcule_score(Message) -> ??? case gen_tcp:connect("localhost", 783, [{mode, binary}]) of ??????? {ok, Sock} -> ??? ??? ??? ? ??????????? gen_tcp:send(Sock, Message2); ??????? {error,_} -> ??????????? io:fwrite("Connection error! Quitting...~n") ??? end. TCP?socket is nice to talk with spamassassin, it returns me a 3-tuple with binary string data like that: {tcp,#Port<0.55>,<<"SPAMD/1.1 0 EX_OK\r\nContent-length: 564\r\nSpam: True ; 7.9 / 5.0\r\n\r\nReceived: from localhost by XXXX.ikexpress.com\n\twith SpamAssassin (version 3.4.2);\n\tThu, 15 Aug 2019 21:44:12 +0200\nX-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on\n\tXXXXX.ikexpress.com\nX-Spam-Flag: YES\nX-Spam-Level: *******\nX-Spam-Status: Yes, score=7.9 required=5.0 tests=EMPTY_MESSAGE,MISSING_DATE,\n\tMISSING_FROM,MISSING_HEADERS,MISSING_MID,MISSING_SUBJECT,\n\tNO_HEADERS_MESSAGE,NO_RECEIVED,NO_RELAYS autolearn=no\n\tautolearn_force=no version=3.4.2\nMIME-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"----------=_5D55B60C.D2FC2670\"\n\n">>} The loop in the second handle_info match OK the answer from the listening gen_tcp server, but I have to do the packaging to send it to a topic Exchange (topic_scored_email exchange) ***scored_email*** main(Argv) -> ??? {ok, Connection} = amqp_connection:start(#amqp_params_network{virtual_host = <<"/">>}), ??? {ok, Channel} = amqp_connection:open_channel(Connection), ??? amqp_channel:call(Channel, #'exchange.declare'{exchange = <<"topic_scored_email">>,type = <<"topic">>}), ??? {RoutingKey, Message} = case Argv of ??????????????????????????????? ? %DOING?PATTERN?MATCHING?THAT?WORKS?HERE ??? ??? ??? ??? ??? ??? ??? ??? ? ??????????????????????????? end, ??? amqp_channel:cast(Channel,#'basic.publish'{exchange = <<"topic_scored_email">>,routing_key = RoutingKey},#amqp_msg{payload = Message}), First issue is type of the data (binary string) but I guess it can be workarounded using BIF binary_to_tuple or stuff like that. What I struggle to understand is how I could pass the righ RoutingKey, since Erlang is functionnal, there is no side effect or assignation. That change in format data (AMQP --> raw tcp --> then AMQP again) seems impossible (to me) to achieve with OTP abstraction However I would like to reassemble every processed message with the right routing key matched 5 lines above. How could I modify my code, to do that ? I come from imperative language and reach my limit here? Yours PS I know it is more a rabbitmq issue and I might be more successful to post on stackoverflow or rabbitmq google groups but I feel #Erlang-questions could come handy on that topic From micaelnussbaumer@REDACTED Sat Aug 17 17:23:46 2019 From: micaelnussbaumer@REDACTED (Micael Nussbaumer) Date: Sat, 17 Aug 2019 16:23:46 +0100 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: Message-ID: Hi, thank you all for your inputs. I ended up doing a trace as Raimo suggested and it works fine the test I think I could also have implemented `format_status` for the gen_statem and extract the timers tuple from it? Not sure. Regarding having an API for it I think it could be useful since that implementation detail is opaque. Torben, thank you sharing your lib - it looks like it can be quite handy but in this particular case it's for a library as well and I would rather not use a dependency, and since the timer options in the gen_statem work great by default I would like to keep using those instead of incurring another message to set the timer & executing a callback. I can definitively understand the appeal of having it instead be mockable though. For the timeouts when I wrote the module that uses these timers I added the option of setting their value on start, so that indeed I would be able to test the behaviour easily in terms of ms and for that part it works great. It was just this detail that was bugging me. On the other hand, mocking also introduces a layer of "this passes the tests but in reality it's not being tested" correct? I'm not very familiar with mocking in tests. Roger, thank you so much for taking the time to extract that! So I ended up doing the state inspection instead, I haven't used dbg yet but it looks like it can be useful. What is the difference between using dbg instead of the bare trace? I guess now by looking at your example that indeed I could have done the same approach by tracing the timer sets/cancels instead of tracing the call functions and extracting the state, that is probably cleaner. Raimo, I replied to you by accident privately when using the list web gui - I thought it was going to the "thread" as a reply to you. And yes, perhaps on the sys:get_status it could include by default/on option also an element for the timers? I did in fact try calling that at some point after your first reply: {data,[{"Status",running}, {"Parent",<0.86.0>}, {"Logged Events",[]}, {"Postponed",[]}]}, Anyway, thank you all, great reading your replies, Micael -------------- next part -------------- An HTML attachment was scrubbed... URL: From mark.geib.44@REDACTED Mon Aug 19 04:30:49 2019 From: mark.geib.44@REDACTED (Mark Geib) Date: Sun, 18 Aug 2019 20:30:49 -0600 Subject: [erlang-questions] igmp v3 and join source specific multicast Message-ID: Using the code below I am able to join a source specific multicast group and receive the datagrams from the specified source. However, when I open a second socket and join a second group, i.e. different multicast address, I start to see the datagrams from both groups on both sockets. Any ideas would be greatly appreciated. Bin = << GroupIp/binary, LocalIp/binary, SourceIp/binary >>, {ok, Socket} = gen_udp:open(Port, [inet, binary, {active,true}, {reuseaddr,true}, {recbuf, RecBuf}, {buffer, Buffer}, {read_packets, ReadPackets}, {raw, 0, 39, Bin}]), Thanks, Mark. From sergej.jurecko@REDACTED Mon Aug 19 07:36:54 2019 From: sergej.jurecko@REDACTED (=?utf-8?Q?Sergej_Jure=C4=8Dko?=) Date: Mon, 19 Aug 2019 07:36:54 +0200 Subject: [erlang-questions] igmp v3 and join source specific multicast In-Reply-To: References: Message-ID: Why do you use raw instead of multicast options in gen_udp:open ? Regards, Sergej > On 19 Aug 2019, at 04:30, Mark Geib wrote: > > Using the code below I am able to join a source specific multicast > group and receive the datagrams from the specified source. However, > when I open a second socket and join a second group, i.e. different > multicast address, I start to see the datagrams from both groups on > both sockets. Any ideas would be greatly appreciated. > > Bin = << GroupIp/binary, LocalIp/binary, SourceIp/binary >>, > > {ok, Socket} = gen_udp:open(Port, > [inet, > binary, > {active,true}, > {reuseaddr,true}, > {recbuf, RecBuf}, > {buffer, Buffer}, > {read_packets, ReadPackets}, > {raw, 0, 39, Bin}]), > > Thanks, > Mark. > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions From mark.geib.44@REDACTED Mon Aug 19 16:28:17 2019 From: mark.geib.44@REDACTED (Mark Geib) Date: Mon, 19 Aug 2019 08:28:17 -0600 Subject: [erlang-questions] igmp v3 and join source specific multicast In-Reply-To: References: Message-ID: <07B99C48-BE08-4B48-BCC8-DF17FD6D3621@gmail.com> AFAIK there are no options currently for supporting source specific multicast, SSM. Mark. > On Aug 18, 2019, at 11:36 PM, Sergej Jure?ko wrote: > > Why do you use raw instead of multicast options in gen_udp:open ? > > > Regards, > Sergej > >> On 19 Aug 2019, at 04:30, Mark Geib wrote: >> >> Using the code below I am able to join a source specific multicast >> group and receive the datagrams from the specified source. However, >> when I open a second socket and join a second group, i.e. different >> multicast address, I start to see the datagrams from both groups on >> both sockets. Any ideas would be greatly appreciated. >> >> Bin = << GroupIp/binary, LocalIp/binary, SourceIp/binary >>, >> >> {ok, Socket} = gen_udp:open(Port, >> [inet, >> binary, >> {active,true}, >> {reuseaddr,true}, >> {recbuf, RecBuf}, >> {buffer, Buffer}, >> {read_packets, ReadPackets}, >> {raw, 0, 39, Bin}]), >> >> Thanks, >> Mark. >> _______________________________________________ >> erlang-questions mailing list >> erlang-questions@REDACTED >> http://erlang.org/mailman/listinfo/erlang-questions > From hello@REDACTED Tue Aug 20 09:33:11 2019 From: hello@REDACTED (Adam Lindberg) Date: Tue, 20 Aug 2019 09:33:11 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: <20190816134720.GA77661@erix.ericsson.se> References: <20190816084343.GA43696@erix.ericsson.se> <20190816134720.GA77661@erix.ericsson.se> Message-ID: <4153DE0D-78CC-49FF-A598-522FCA400EA3@alind.io> I concur with Jesper and Fred. Timer data should be injected into the process, with a sensible production default. Personally I would keep all the different timer values in a map in the process state, seeded by a default argument in my own MyProc:star_link/X function. This map can then be merged with an optional map supplied by the user. When a timer is started in gen_statem, you would do a lookup in this map based on e.g. the timer name. For tests, you could then inject a custom map where you override some timer values to match what is desired for the test. In my opinion, no extra support in gen_statem is needed for this. Relying on shorter but still not exactly precise timeouts in tests is still tricky. What could be useful to have support for in gen_statem is firing the timeout events manually. I.e. in a test where you set up the timer in gen_statem, there would then be a way to manually fire a timer event in a gen_statem process. That way, the test becomes very readable and deterministic. Not sure how such an API would look like though. Cheers, Adam > On 16. Aug 2019, at 15:47, Raimo Niskanen wrote: > > On Fri, Aug 16, 2019 at 12:36:29PM +0200, Torben Hoffmann wrote: >> On Fri, 16 Aug 2019 at 10:43, Raimo Niskanen < >> raimo+erlang-questions@REDACTED> wrote: >> >>> On Thu, Aug 15, 2019 at 06:44:43PM +0200, Torben Hoffmann wrote: >>>> Hi Micael, >>>> >>>> I'm very biassed here, but apart from my creator fondness many of my >>>> colleagues are very happy about the approach that my Chronos library >>> takes >>>> when it comes to timers. >>>> >>>> https://github.com/lehoff/chronos >>> >>> I notice that in that README.md you compare Chronos with the timeout >>> feature >>> in gen_server and gen_fsm. The timers in gen_statem were specifically >>> designed to remedy most of their shortcomings. >>> >>> So, from a usability point of view, can you elaborate what Cronos >>> can do better than gen_statem timers? >>> >>> I have a todo to update the README.md to cover gen_statem as well - thanks >> for reminding me! > > Great! No problem ;-) > >> >> I have worked a lot with gen_statem - absolutely a very good component and >> easy to work with. > > Always nice to hear! :-) > >> But the problem of mocking still remains the same. >> When testing I prefer to mock time so that I don't have to wait for the >> timeout to occur. >> Furthermore, I'm so heavily influenced by my ten years at Motorola that I >> want the timers to stand out as in all the nice SDL diagrams in the >> standards shows. >> That means that I want an easy way to check that a timer has been started >> (mock the call to chronos:start_timer()) and then an easy way to induce the >> expiry of said timer without having to wait for whatever the delay is. >> When you have timers in the minutes range you just don't want your >> automated tests to wait it out. >> >> If there is a way to avoid this with gen_statem I'd be most interested! > > Not today. > > For debugging only, not mocking, it would be possible to log timer actions > in the sys log, and to include timer statistics i.e the number of running > timers or a list of them in sys:get_status/1. > > Would that be interesting fetures? > > For mocking, a possible new feature would be to make the calls to > erlang:start_timer/4 and erlang:cancel_timer/1 pluggable, i.e call them > through fun:s. Then the plugged in functions may for example communicate > with a registered timer server that can do as it pleases about when to > fire timeouts, log timer starts and cancels, etc... > > How dynamic would such a feature need to be? > * An option to gen_statem:start{,_link}/3,4? > * Read application variable at server start? > * Return an action from the callback module (so the callback module > can implement a function to activate mocking)? > * Other suggestions? > > Interesting topic - I did not forsee this need... > > BRs > / Raimo > > >> >> Cheers, >> Torben >> >> >>>> >>>> Basically, don't use the internal timers, but do read the full README >>> from >>>> Chronos. >>>> >>>> Very happy to assist you and improve anything in Chronos, if you find it >>>> confusing. >>>> >>>> Cheers, >>>> Torben >>>> >>>> On Thu, 15 Aug 2019 at 13:35, Micael Nussbaumer < >>> micaelnussbaumer@REDACTED> >>>> wrote: >>>> >>>>> Hi, first time poster (but I've read many threads in here). >>>>> >>>>> How does one usually test gen_statem internal timer events? >>>>> Usually you test the effects of the behaviour somehow, and I can test >>>>> that. But in this particular case I had a situation where timers with >>> uniq >>>>> references are created, later on they usually get removed and all is >>> fine - >>>>> they're created for each extra worker started and at some point the >>> worker >>>>> is removed by the timer event that trigger checking some conditions. >>>>> >>>>> I noticed after that, the way I had written it, if an extra worker was >>>>> started then died for some other reason than the timer event taking it >>> out, >>>>> I could theoretically accumulate timers that wouldn't be removed, I've >>>>> since then corrected that but still I have no tests ensuring me that it >>>>> actually works. >>>>> So my question is if there's any even way to test it (even if with >>>>> tracing)? >>>>> Thanks >>>>> >>>>> *M*icael *N*ussbaumer >>>>> artistic portfolio >>>>> >>>> >>>> >>>> -- >>>> http://www.linkedin.com/in/torbenhoffmann >>>> @LeHoff >>> >>> >>> -- >>> >>> / Raimo Niskanen, Erlang/OTP, Ericsson AB >>> _______________________________________________ >>> erlang-questions mailing list >>> erlang-questions@REDACTED >>> http://erlang.org/mailman/listinfo/erlang-questions >>> >> >> >> -- >> http://www.linkedin.com/in/torbenhoffmann >> @LeHoff > >> _______________________________________________ >> erlang-questions mailing list >> erlang-questions@REDACTED >> http://erlang.org/mailman/listinfo/erlang-questions > > > -- > > / Raimo Niskanen, Erlang/OTP, Ericsson AB > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions From v@REDACTED Tue Aug 20 14:26:01 2019 From: v@REDACTED (Valentin Micic) Date: Tue, 20 Aug 2019 14:26:01 +0200 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 Message-ID: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> Hi all, Recently I?ve made a silly mistake. I wrote: case Payload of <<_:4/binary-unit:8, _:255, _:7/binary-unit:8, 0:16>> -> Payload; _ -> throw( drop ) end Instead of: case Payload of <<_:4/binary-unit:8, 255:8, _:7/binary-unit:8, 0:16>> -> Payload; _ -> throw( drop ) end Considering that overall pattern (which erroneously references 255 bits long field, instead of an octet with a value of 255 ) is not aligned to 8-bit boundary, is it unreasonable to expect the compiler to report this as a potential problem, or at least generate a warning (support for bit-fields notwithstanding). What am I missing here? V/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From mononcqc@REDACTED Tue Aug 20 15:13:51 2019 From: mononcqc@REDACTED (Fred Hebert) Date: Tue, 20 Aug 2019 09:13:51 -0400 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> References: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> Message-ID: On Tue, Aug 20, 2019 at 8:26 AM Valentin Micic wrote: > Hi all, > > Recently I?ve made a silly mistake. I wrote: > > case Payload of > <<_:4/binary-unit:8, _:*255*, _:7/binary-unit:8, 0:16>> -> Payload; > _ -> throw( drop ) > end > > > Considering that overall pattern (which erroneously references 255 bits > long field, instead of an octet with a value of 255 ) is not aligned to > 8-bit boundary, is it unreasonable to expect the compiler to report this as > a potential problem, or at least generate a warning (support for > bit-fields notwithstanding). > > What am I missing here? > > There are informally two kinds of binaries: 8-bit aligned binaries (regular ones) are those people call 'binaries', and then you have bitstrings. Bitstrings don't need any alignment whatsoever. Your pattern can be made to work by using any fitting bitstring. For example: 1> <<_:4/binary-unit:8, _:255, _:7/binary-unit:8, 0:16>> = <<0:(32+255+7*8+16)>>. <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,...>> But more generally, the binary/bitstring distinction will make sense when pattern matching: 3> <<_:4/binary-unit:8, _/binary>> = <<0:(32+255+7*8+16)>>. ** exception error: no match of right hand side value <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,...>> 4> <<_:4/binary-unit:8, _/bitstring>> = <<0:(32+255+7*8+16)>>. <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,...>> 5> <<_:4/binary-unit:8, _/bits>> = <<0:(32+255+7*8+16)>>. <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,...>> Note that bits is shorthand for bitstring. Do note as well that you can always cheat the pattern match by specifying units: 6> <<_:4/binary-unit:8, _/binary-unit:1>> = <<0:(32+255+7*8+16)>>. <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,...>> Nothing in Erlang actually mandates exact alignment, it's just that with the default widths of various types impacts pattern matching. Dialyzer, however, does enforce some semantic values. Here's a sample module: -module(chk). -export([f/0, f/1, g/0, g/1]). f() -> f(<<0:17>>). g() -> g(<<0:17>>). -spec f(binary()) -> ok. f(Bin) -> <<_/binary>> = Bin, ok. -spec g(binary()) -> ok. g(Bin) -> <<_/bits>> = Bin, ok. If you run dialyzer on it, you'll find out the following: chk.erl:4: Function f/0 has no local return chk.erl:4: The call chk:f(<<_:17>>) will never return since the success typing is (binary()) -> 'ok' and the contract is (binary()) -> 'ok' chk.erl:5: Function g/0 has no local return chk.erl:5: The call chk:g(<<_:17>>) breaks the contract (binary()) -> 'ok' the type binary(), to Dialyzer, implies the 8-bit alignment you're looking after. The bitstring() type will not care for alignment. This is because Dialyzer supports defining binary types as: <<>> %% empty binary <<_:M>> %% fixed-size binary, where M is a positive integer <<_:_*N>> %% variable-size binary with an alignment on N <<_:M, _:_*N>> %% binary of at least M size, with a variable-sized tail aligned on N Essentially, binary() is defined as <<_:_*8>> and bitstring() is defined as <<_:_*1>>. This lets you encode whatever check semantics you'd like within type specifications, and Dialyzer can try to figure it out for you. But nothing, by default, would necessarily warrant compiler warnings since alignment on 8 bits is not mandated by the runtime. -------------- next part -------------- An HTML attachment was scrubbed... URL: From torben.lehoff@REDACTED Tue Aug 20 15:30:31 2019 From: torben.lehoff@REDACTED (Torben Hoffmann) Date: Tue, 20 Aug 2019 15:30:31 +0200 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: <20190816134720.GA77661@erix.ericsson.se> References: <20190816084343.GA43696@erix.ericsson.se> <20190816134720.GA77661@erix.ericsson.se> Message-ID: On Fri, 16 Aug 2019 at 15:47, Raimo Niskanen < raimo+erlang-questions@REDACTED> wrote: > > > But the problem of mocking still remains the same. > > When testing I prefer to mock time so that I don't have to wait for the > > timeout to occur. > > Furthermore, I'm so heavily influenced by my ten years at Motorola that I > > want the timers to stand out as in all the nice SDL diagrams in the > > standards shows. > > That means that I want an easy way to check that a timer has been started > > (mock the call to chronos:start_timer()) and then an easy way to induce > the > > expiry of said timer without having to wait for whatever the delay is. > > When you have timers in the minutes range you just don't want your > > automated tests to wait it out. > > > > If there is a way to avoid this with gen_statem I'd be most interested! > > Not today. > > For debugging only, not mocking, it would be possible to log timer actions > in the sys log, and to include timer statistics i.e the number of running > timers or a list of them in sys:get_status/1. > > Would that be interesting fetures? > > For mocking, a possible new feature would be to make the calls to > erlang:start_timer/4 and erlang:cancel_timer/1 pluggable, i.e call them > through fun:s. Then the plugged in functions may for example communicate > with a registered timer server that can do as it pleases about when to > fire timeouts, log timer starts and cancels, etc... > > How dynamic would such a feature need to be? > * An option to gen_statem:start{,_link}/3,4? > * Read application variable at server start? > * Return an action from the callback module (so the callback module > can implement a function to activate mocking)? > * Other suggestions? > > Interesting topic - I did not forsee this need... > > BRs > / Raimo > I like the idea of making the calls to start an cancel timers pluggable. The key requirement is that there is a function call that one can detect and that the start of a timer doesn't actually trigger the creation of a timer since one needs the ability to inject the timer expiry into the gen_statem when the test calls for it. On that note it might not be good to just expose the erlang:*_timer() functions as they would be un-mockable. Maybe something like a call to a dummy function when the timers start/cancel. That can be mocked or spotted by a trace. And then a way to inject by using a function in the gen_statem module that would only work in timers_testing mode. I would welcome this as an option to gen_statem:start{,_link}/3,4 that one would only use for testing. It should simply turn the erlang:*_timer() calls into calls to those dummy functions. This seems like the least invasive way of doing it. And then we can all expect a beer from the first person to ship to production with the testing_timers option ;-) Given that gen_statem has introduced the notion of generic timeouts a mechanism such as the above would render Chronos superfluous when it comes to testing timers with gen_statem. I would welcome that despite all the help I have gotten from Chronos over the years. Cheers, Torben -- http://www.linkedin.com/in/torbenhoffmann @LeHoff -------------- next part -------------- An HTML attachment was scrubbed... URL: From v@REDACTED Tue Aug 20 17:04:26 2019 From: v@REDACTED (Valentin Micic) Date: Tue, 20 Aug 2019 17:04:26 +0200 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: References: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> Message-ID: <3B77EB0C-2E21-4AFE-8427-6F78F956E987@micic.co.za> Hi Fred, I should have used a more appropriate erlang term ?bitstring" as opposed to ?bit field? in my email ? thank you for correcting this. I?ve been using bitstrings in the past, well, not really as a bunch of ?loose? bits, but always as a part of some other binary pattern aligned to 8-bit boundary. If you cannot write 17 loose bits to a file, or, better yet, if you cannot send 13 loose bits over a socket, one has to wonder how useful are non-aligned bitstrings (and by this I mean ?loose? bits). And it gets worse. Consider this: (tsdb_1_1@REDACTED)433> term_to_binary( <<0:8>> ). <<131,109,0,0,0,1,0>> (tsdb_1_1@REDACTED)434> term_to_binary( <<0:1>> ). <<131,77,0,0,0,1,1,0>> It follows that it takes more memory to store 1 loose bit than 8 aligned bits. And just to prove that if it walks like a duck, and quacks like a duck, it's probably? an elephant. (tsdb_1_1@REDACTED)449> is_binary( <<0:8>> ). true (tsdb_1_1@REDACTED)448> is_binary( <<0:1>> ). false But, if you put two elephants next to each other, you get ? a duck! is_binary( <<0:5, 0:3>> ). true Given all this, why would anyone find bitstrings useful? But, the above notwithstanding, I understood your point that run-time does not mandate any kind of alignment, hence compiler has nothing to report. Makes sense ? Thank you. V/ > On 20 Aug 2019, at 15:13, Fred Hebert wrote: > > On Tue, Aug 20, 2019 at 8:26 AM Valentin Micic > wrote: > Hi all, > > Recently I?ve made a silly mistake. I wrote: > > case Payload of > <<_:4/binary-unit:8, _:255, _:7/binary-unit:8, 0:16>> -> Payload; > _ -> throw( drop ) > end > > > Considering that overall pattern (which erroneously references 255 bits long field, instead of an octet with a value of 255 ) is not aligned to 8-bit boundary, is it unreasonable to expect the compiler to report this as a potential problem, or at least generate a warning (support for bit-fields notwithstanding). > > What am I missing here? > > > There are informally two kinds of binaries: 8-bit aligned binaries (regular ones) are those people call 'binaries', and then you have bitstrings. Bitstrings don't need any alignment whatsoever. Your pattern can be made to work by using any fitting bitstring. For example: > > 1> <<_:4/binary-unit:8, _:255, _:7/binary-unit:8, 0:16>> = <<0:(32+255+7*8+16)>>. > <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, > 0,...>> > > But more generally, the binary/bitstring distinction will make sense when pattern matching: > > 3> <<_:4/binary-unit:8, _/binary>> = <<0:(32+255+7*8+16)>>. > ** exception error: no match of right hand side value <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, > 0,...>> > 4> <<_:4/binary-unit:8, _/bitstring>> = <<0:(32+255+7*8+16)>>. > <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, > 0,...>> > 5> <<_:4/binary-unit:8, _/bits>> = <<0:(32+255+7*8+16)>>. > <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, > 0,...>> > > Note that bits is shorthand for bitstring. Do note as well that you can always cheat the pattern match by specifying units: > > 6> <<_:4/binary-unit:8, _/binary-unit:1>> = <<0:(32+255+7*8+16)>>. > <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, > 0,...>> > > Nothing in Erlang actually mandates exact alignment, it's just that with the default widths of various types impacts pattern matching. Dialyzer, however, does enforce some semantic values. Here's a sample module: > > -module(chk). > -export([f/0, f/1, g/0, g/1]). > > f() -> f(<<0:17>>). > g() -> g(<<0:17>>). > > -spec f(binary()) -> ok. > f(Bin) -> > <<_/binary>> = Bin, > ok. > > -spec g(binary()) -> ok. > g(Bin) -> > <<_/bits>> = Bin, > ok. > > If you run dialyzer on it, you'll find out the following: > > chk.erl:4: Function f/0 has no local return > chk.erl:4: The call chk:f(<<_:17>>) will never return since the success typing is (binary()) -> 'ok' and the contract is (binary()) -> 'ok' > chk.erl:5: Function g/0 has no local return > chk.erl:5: The call chk:g(<<_:17>>) breaks the contract (binary()) -> 'ok' > > the type binary(), to Dialyzer, implies the 8-bit alignment you're looking after. The bitstring() type will not care for alignment. This is because Dialyzer supports defining binary types as: > <<>> %% empty binary > <<_:M>> %% fixed-size binary, where M is a positive integer > <<_:_*N>> %% variable-size binary with an alignment on N > <<_:M, _:_*N>> %% binary of at least M size, with a variable-sized tail aligned on N > Essentially, binary() is defined as <<_:_*8>> and bitstring() is defined as <<_:_*1>>. This lets you encode whatever check semantics you'd like within type specifications, and Dialyzer can try to figure it out for you. But nothing, by default, would necessarily warrant compiler warnings since alignment on 8 bits is not mandated by the runtime. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From empro2@REDACTED Tue Aug 20 18:55:06 2019 From: empro2@REDACTED (empro2@REDACTED) Date: Tue, 20 Aug 2019 18:55:06 +0200 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: <3B77EB0C-2E21-4AFE-8427-6F78F956E987@micic.co.za> References: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> <3B77EB0C-2E21-4AFE-8427-6F78F956E987@micic.co.za> Message-ID: <20190820185506.4ef381d7@raspy> On Tue, 20 Aug 2019 17:04:26 +0200 Valentin Micic wrote: > (tsdb_1_1@REDACTED)448> is_binary( <<0:1>> ). > > false "is elephant?" is encoded in Erlang as: is_bitstring/1 75> is_bitstring(<<0:1>>). is_bitstring(<<0:1>>). true > But, if you put two elephants next to each other, you get > ? a duck! > > is_binary( <<0:5, 0:3>> ). > > true Read "is_binary/1" as "is_bitstring/1 and (bitlength_of(Elephants) mod 8 == 0)" :-) > Given all this, why would anyone find bitstrings useful? That is why the default bitstring is a bytestring or octetstring or binary: 98> is_binary(<<"blah">>) and is_binary(<<1, 2, 3>>). is_binary(<<"blah">>) and is_binary(<<1, 2, 3>>). true As long as you do not tell the compiler to take bites of memory that are no bytes, with that ":", the two of you seem to agree there. Might help when extracting flag bits? (or when talking to some 9-bit byte PDP ... or was that 11? ... ;-) Anyway I would rather deprecate and obsolete away dot notation for record elements ... /Michael -- Normality is merely a question of quantity, not of quality. From v@REDACTED Tue Aug 20 20:44:02 2019 From: v@REDACTED (Valentin Micic) Date: Tue, 20 Aug 2019 20:44:02 +0200 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: <20190820185506.4ef381d7@raspy> References: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> <3B77EB0C-2E21-4AFE-8427-6F78F956E987@micic.co.za> <20190820185506.4ef381d7@raspy> Message-ID: > On 20 Aug 2019, at 18:55, empro2@REDACTED wrote: > > On Tue, 20 Aug 2019 17:04:26 +0200 > Valentin Micic wrote: > >> (tsdb_1_1@REDACTED)448> is_binary( <<0:1>> ). >> >> false > > "is elephant?" is encoded in Erlang as: is_bitstring/1 I see? nevertheless, I prefer is_duck/1, but thank you :-) > > 75> is_bitstring(<<0:1>>). > is_bitstring(<<0:1>>). > true > > >> But, if you put two elephants next to each other, you get >> ? a duck! >> >> is_binary( <<0:5, 0:3>> ). >> >> true > > Read "is_binary/1" as > "is_bitstring/1 and (bitlength_of(Elephants) mod 8 == 0)" > > :-) > >> Given all this, why would anyone find bitstrings useful? > > That is why the default bitstring is a bytestring or > octetstring or binary: > > 98> is_binary(<<"blah">>) and is_binary(<<1, 2, 3>>). > is_binary(<<"blah">>) and is_binary(<<1, 2, 3>>). > true > > As long as you do not tell the compiler to take bites of > memory that are no bytes, with that ":", the two of you seem > to agree there. > > Might help when extracting flag bits? (or when talking to > some 9-bit byte PDP ... or was that 11? ... ;-) Anyway I > would rather deprecate and obsolete away dot notation for > record elements ? > Yes, you could use bit-syntax to extract flags, however, I doubt this will ever be presented to Erlang as a stream of bits (well, at least not nowadays) ? unless, of course, Erlang runs on top of the underlying hardware that natively supports 9-bit bytes, of course. And how many of these are available to us today? By contrast, the record dot notation is just a syntactic sugar, not a data type. You could chose not to use it (I never do, so no love lost if, or when they remove it). However, a defective usage of record dot syntax may not accidentally introduce a semantic problem, as compiler would definitely help you with identifying a problematic syntax (well, I know, strictly speaking this is not quite true, but go with it, as this is true for record syntax in general, but not to dot notation as such). Unlike situation I?ve described, where I have accidentally introduced a semantic, but not a syntax error (for the reasons Frank explained). Oh, please, don?t get me wrong, I like the ability to write <> = <>. However, with this construct, you could still extract your flags, but this would not require any new data type (such as bitstring) ? e.g. is_binary(<> = <>) will merrily report true. Contrast this with <> = Some6BitBitstring; which, In order to work, must have Some6BitBitstring set to exactly a six-bit Bitstring, which could only be set from within Erlang runtime, thus fairly artificial construct with respect to the environment, e.g. OS, socket, files, etc. Thus, my assertion is that bitstring is a pretty pointless data type. There. > /Michael > > -- > > Normality is merely a question of quantity, > not of quality. > But, according to Hegelian dialectics, quantity transforms into quality and vice-versa :-) > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mononcqc@REDACTED Tue Aug 20 21:20:54 2019 From: mononcqc@REDACTED (Fred Hebert) Date: Tue, 20 Aug 2019 15:20:54 -0400 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: References: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> <3B77EB0C-2E21-4AFE-8427-6F78F956E987@micic.co.za> <20190820185506.4ef381d7@raspy> Message-ID: On Tue, Aug 20, 2019 at 2:44 PM Valentin Micic wrote: > > Oh, please, don?t get me wrong, I like the ability to write < Group:2, User:2, *_:2*>> = <>. > However, with this construct, you could still extract your flags, but this > would not require any new data type (such as bitstring) ? e.g. is_binary(< Group:2, User:2, *_:2*>> = <>) will merrily report true. > > Contrast this with <> = Some6BitBitstring; > > which, In order to work, must have Some6BitBitstring set to exactly a > six-bit Bitstring, which could only be set from within Erlang runtime, thus > fairly artificial construct with respect to the environment, e.g. OS, > socket, files, etc. > > Thus, my assertion is that bitstring is a pretty pointless data type. > There. > Well, let's take a TCP packet header for example; if you follow the current wikipedia definition with experimental RFCs, there are 3 reserved bits, followed by all the flags, set on 9 bits. You could either need to pattern match all the flags individually, but you can also write, thanks to Erlang and bitstrings, a function that accepts a pattern like <<..., _Reserved:3, Flags:9/bits, ...>> and then ask decode_flags(Flags) to return you a list of atoms for all the values that are set. This might actually be desirable because some flags change meaning according to other flags; the ECE flag's value can be triple depending on whether it is 0, or whether it is 1 and the current value of the SYN flag being set (1 or 0). You can obviously work around this, but if you do it C-style, you're likely to have to gobble the reserved bits along with the flags, and then extract the experimental flag from the reserved bits, and carry it as an extra value somewhere. Mostly, there's interesting stuff that you can do with bitstrings that are matched-out sections of 8-bit aligned binaries, regardless of where you are reading them from and what the initial machine alignment was. -------------- next part -------------- An HTML attachment was scrubbed... URL: From steve@REDACTED Tue Aug 20 21:24:14 2019 From: steve@REDACTED (Steve Strong) Date: Tue, 20 Aug 2019 20:24:14 +0100 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 Message-ID: Or take SDI, where each word is 10bits... bitstring is invaluable. Sent from my iPhone > On 20 Aug 2019, at 20:21, Fred Hebert wrote: > From dszoboszlay@REDACTED Tue Aug 20 22:13:37 2019 From: dszoboszlay@REDACTED (=?UTF-8?Q?D=C3=A1niel_Szoboszlay?=) Date: Tue, 20 Aug 2019 22:13:37 +0200 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: References: Message-ID: Bit strings could come very handy for compression algorithms too, say Huffman coding a byte stream. Yes, at the end you may have to pad the bitstring to get whole bytes that you can save to a file or send over the network, but until then it's very useful that your buffer can have an arbitrary length. Bitstrings are rarely needed, but when you need them, it's Godsent that the language has excellent support for this data type! On Tue, 20 Aug 2019 at 21:24, Steve Strong wrote: > Or take SDI, where each word is 10bits... bitstring is invaluable. > > Sent from my iPhone > > > On 20 Aug 2019, at 20:21, Fred Hebert wrote: > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lloyd@REDACTED Tue Aug 20 23:29:50 2019 From: lloyd@REDACTED (lloyd@REDACTED) Date: Tue, 20 Aug 2019 17:29:50 -0400 (EDT) Subject: [erlang-questions] Erlang version confusion Message-ID: <1566336590.033616904@apps.rackspace.com> Hello, I have Erlang Version 19.0 installed long-ago on my dev system. While testing Nitrogen code my app crashed due to the pesky string library revision problem: string:lexemes/2 was not to be found. OK, so time to update my working version of Erlang. I have kerl. Piece of cake. This was indeed successful: $ erl Erlang/OTP 22 [erts-10.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] However, when I try to rebuild my Nitrogen app, it still builds under Erlang Version 19.0. Here's kerl status: $ kerl status Available builds: 21.1,21.1 21.1,21.1-builtdocs 22.0,22.0 ---------- Available installations: 21.1 /home/lloyd/Kerl/21.1 22.0 /home/lloyd/Kerl/22.0 ---------- No Erlang/OTP installation is currently active Looks like it might be useful to bring Version 19.0 under kerl. But, problem, I don't know how to decommission the old 19.0 installation. Can anyone provide the magic incantation? Many thanks, LRP From v@REDACTED Wed Aug 21 00:23:01 2019 From: v@REDACTED (Valentin Micic) Date: Wed, 21 Aug 2019 00:23:01 +0200 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: References: Message-ID: > On 20 Aug 2019, at 22:13, D?niel Szoboszlay wrote: > > Bit strings could come very handy for compression algorithms too, say Huffman coding a byte stream. Yes, at the end you may have to pad the bitstring to get whole bytes that you can save to a file or send over the network, but until then it's very useful that your buffer can have an arbitrary length. Bitstrings are rarely needed, but when you need them, it's Godsent that the language has excellent support for this data type! For what is worth, I agree ? compression algorithm implementation may benefit from Bitstrings. > > On Tue, 20 Aug 2019 at 21:24, Steve Strong > wrote: > Or take SDI, where each word is 10bits... bitstring is invaluable. > > Sent from my iPhone > > > On 20 Aug 2019, at 20:21, Fred Hebert > wrote: > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions -------------- next part -------------- An HTML attachment was scrubbed... URL: From raoknz@REDACTED Wed Aug 21 02:06:56 2019 From: raoknz@REDACTED (Richard O'Keefe) Date: Wed, 21 Aug 2019 12:06:56 +1200 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: <3B77EB0C-2E21-4AFE-8427-6F78F956E987@micic.co.za> References: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> <3B77EB0C-2E21-4AFE-8427-6F78F956E987@micic.co.za> Message-ID: Valentin Micic wrote :> If you cannot write 17 loose bits to a file, or, :> better yet, if you cannot send 13 loose bits over a socket, :> one has to wonder how useful are non-aligned bitstrings This is a very odd thing to say. PL/I has had bit strings since about 1965. Common Lisp has bit strings. Some Scheme implementations have bit strings. APL has bit arrays of any size and shape. SQL 92 had BIT(n) and BIT(n) VARYING just like PL/I -- surprise surprise -- but SQL 2003 dropped them, while Postgres still supports them. Ada has bit strings, in the guise of packed arrays of Boolean, replacing Pascal's sets (which are fixed size bit strings). Do I need to point to bit string support in Java and C#? You may not be able to send 13 loose bits over a socket, but you *can* have a 13-bit field in a packet, and why should it be hard to construct that 13-bit field or to pack it? And of course if you are running Erlang on a Raspberry Pi, you can send or receive a message of *any* number of bits through the Pi's GPIO pins (with the aid of a NIF). -------------- next part -------------- An HTML attachment was scrubbed... URL: From be.dmitry@REDACTED Wed Aug 21 07:24:17 2019 From: be.dmitry@REDACTED (Dmitry Belyaev) Date: Wed, 21 Aug 2019 15:24:17 +1000 Subject: [erlang-questions] Handling routing_key for topic routing in gen_server handle_info In-Reply-To: <8004b4b4-8330-cc28-01a5-059688d1a102@opentelecom.fr> References: <8004b4b4-8330-cc28-01a5-059688d1a102@opentelecom.fr> Message-ID: If we remove all the unrelated implementation details then we see a picture: handle_info({incoming, Id, SomeDetails}, State) -> start_processing(SomeDetails), {noreply, State}; handle_info({processed, Result}, State) -> Id = ???, % how to get the value finalise(Id, Result), {noreply, State} I can suggest the following approaches to do that assuming you cannot force the processor to accept and pass your value back. 1. If you can switch to synchronous processing (which may be desirable to prevent overloading of the processor) you can store the Id in the process State. handle_info({incoming, Id, SomeDetails}, #{current_id := undefined} = State) -> start_processing(SomeDetails), {noreply, State#{current_id => Id}}; handle_info({processed, Result}, #{current_id := Id} = State) -> finalise(Id, Result), {noreply, State#{current_id => undefined}} 2. If the processing must be asynchronous and there may be multiple inflight processings, you can: a) make start_processing to accept the Id and to spawn a new process which would receive the processed message (tcp reponse) handle_info({incoming, Id, SomeDetails}, State) -> spawn_link(fun -> start_processing(SomeDetails), receive {processed, Result} -> finalise(Id, Result) end end), {noreply, State} 3. make mapping from sockets to Ids and keep it in the state handle_info({incoming, Id, SomeDetails}, State) -> Socket = start_processing(SomeDetails), {noreply, State#{Socket => Id}}; handle_info({processed, Socket, Result}, State) -> #{Socket := Id} = State, finalise(Id, Result), {noreply, maps:delete(State, Socket)}. Kind regards, Dmitry Belyaev On Fri, Aug 16, 2019 at 11:51 PM S?bastien BRICE wrote: > Hello there, > > I am a bit new to the Erlang Environment > > I am writing an emailtesting application that filters incoming email > with a randomly generated routing_keys on a topic exchange to make > emails entering my system > > Once they are delivered (and processed) on an queue, I want to label > them again with the previously randomly routing_key to route them to > another exchange to make them ready for the final consume. > > This 2nd producing step is causing me real troubles > > I am getting data back from a tcp socket (processed by a third-tier > program: spamassassin) with handle_info pattern matching > > I rely on a gen_server to consume messages first through the regular > amqp_client/include/amqp_client.hrl Library > > I use handle_info in my gen_server behaviour and then pattern match on > the parameters. > > Detecting delivered AMQP message is done through function heads > (records) in handle_info callback > > ***My gen_server**** > handle_info({#'basic.deliver'{routing_key=Key, consumer_tag=Tag}, > Content}, State) -> > #amqp_msg{props = Properties, payload = Payload} = Content, > #'P_basic'{message_id = MessageId, headers = Headers} = Properties, > send_to_spamassassin:calcule_score(Payload), > {noreply, State}; > handle_info(Msg, State) -> > case Msg of > {_,_,Data} -> > scored_email:main(Data); > {_,_} -> > end, > {noreply, State}. > > ***send_to_spamassassin function *** > calcule_score(Message) -> > case gen_tcp:connect("localhost", 783, [{mode, binary}]) of > {ok, Sock} -> > ? > gen_tcp:send(Sock, Message2); > {error,_} -> > io:fwrite("Connection error! Quitting...~n") > end. > > > TCP socket is nice to talk with spamassassin, it returns me a 3-tuple > with binary string data like that: > > {tcp,#Port<0.55>,<<"SPAMD/1.1 0 EX_OK\r\nContent-length: 564\r\nSpam: > True ; 7.9 / 5.0\r\n\r\nReceived: from localhost by > XXXX.ikexpress.com\n\twith SpamAssassin (version 3.4.2);\n\tThu, 15 Aug > 2019 21:44:12 +0200\nX-Spam-Checker-Version: SpamAssassin 3.4.2 > (2018-09-13) on\n\tXXXXX.ikexpress.com\nX-Spam-Flag: YES\nX-Spam-Level: > *******\nX-Spam-Status: Yes, score=7.9 required=5.0 > tests=EMPTY_MESSAGE,MISSING_DATE,\n\tMISSING_FROM,MISSING_HEADERS,MISSING_MID,MISSING_SUBJECT,\n\tNO_HEADERS_MESSAGE,NO_RECEIVED,NO_RELAYS > > autolearn=no\n\tautolearn_force=no version=3.4.2\nMIME-Version: > 1.0\nContent-Type: multipart/mixed; > boundary=\"----------=_5D55B60C.D2FC2670\"\n\n">>} > > The loop in the second handle_info match OK the answer from the > listening gen_tcp server, but I have to do the packaging to send it to a > topic Exchange (topic_scored_email exchange) > > ***scored_email*** > main(Argv) -> > {ok, Connection} = > amqp_connection:start(#amqp_params_network{virtual_host = <<"/">>}), > {ok, Channel} = amqp_connection:open_channel(Connection), > amqp_channel:call(Channel, #'exchange.declare'{exchange = > <<"topic_scored_email">>,type = <<"topic">>}), > {RoutingKey, Message} = case Argv of > ? > %DOING PATTERN MATCHING THAT WORKS HERE > ? > end, > amqp_channel:cast(Channel,#'basic.publish'{exchange = > <<"topic_scored_email">>,routing_key = RoutingKey},#amqp_msg{payload = > Message}), > > First issue is type of the data (binary string) but I guess it can be > workarounded using BIF binary_to_tuple or stuff like that. > > What I struggle to understand is how I could pass the righ RoutingKey, > since Erlang is functionnal, there is no side effect or assignation. > > That change in format data (AMQP --> raw tcp --> then AMQP again) seems > impossible (to me) to achieve with OTP abstraction > > However I would like to reassemble every processed message with the > right routing key matched 5 lines above. > > How could I modify my code, to do that ? I come from imperative language > and reach my limit here? > > Yours > > PS I know it is more a rabbitmq issue and I might be more successful to > post on stackoverflow or rabbitmq google groups but I feel > #Erlang-questions could come handy on that topic > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From v@REDACTED Wed Aug 21 09:59:48 2019 From: v@REDACTED (Valentin Micic) Date: Wed, 21 Aug 2019 09:59:48 +0200 Subject: [erlang-questions] Bit Syntax and compiler Erlang/OTP R21.1 In-Reply-To: References: <488C7EE4-7E88-4E2E-AB6A-F64640902757@micic.co.za> <3B77EB0C-2E21-4AFE-8427-6F78F956E987@micic.co.za> Message-ID: > On 21 Aug 2019, at 02:06, Richard O'Keefe wrote: > > Valentin Micic wrote > > :> If you cannot write 17 loose bits to a file, or, > :> better yet, if you cannot send 13 loose bits over a socket, > :> one has to wonder how useful are non-aligned bitstrings > > This is a very odd thing to say. PL/I has had bit strings > since about 1965. Common Lisp has bit strings. Some Scheme > implementations have bit strings. APL has bit arrays of any > size and shape. SQL 92 had BIT(n) and BIT(n) VARYING just > like PL/I -- surprise surprise -- but SQL 2003 dropped them, > while Postgres still supports them. Ada has bit strings, > in the guise of packed arrays of Boolean, replacing Pascal's > sets (which are fixed size bit strings). Do I need to point > to bit string support in Java and C#? > > You may not be able to send 13 loose bits over a socket, but > you *can* have a 13-bit field in a packet, and why should it > be hard to construct that 13-bit field or to pack it? Well, as I?ve said, I never had anything against 13-bit field in packet? I was struggling to find a situation where one would benefit from being able to write <> instead of <>, that is ? until Daniel Szoboszlay mentioned compression. Another example from my direct experience (oh irony), which came back to my mind only after Daniels observation, is 7-bit character encoding used by SMS? this would have been way, way easier to implement using bitstrings. I?ve seen the light, thank you. Life moves on. V/ > > And of > course if you are running Erlang on a Raspberry Pi, you can > send or receive a message of *any* number of bits through the > Pi's GPIO pins (with the aid of a NIF). > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mononcqc@REDACTED Wed Aug 21 15:13:37 2019 From: mononcqc@REDACTED (Fred Hebert) Date: Wed, 21 Aug 2019 09:13:37 -0400 Subject: [erlang-questions] Erlang version confusion In-Reply-To: <1566336590.033616904@apps.rackspace.com> References: <1566336590.033616904@apps.rackspace.com> Message-ID: On Tue, Aug 20, 2019 at 5:29 PM wrote: > Hello, > > I have Erlang Version 19.0 installed long-ago on my dev system. While > testing Nitrogen code my app crashed due to the pesky string library > revision problem: string:lexemes/2 was not to be found. > > Looks like it might be useful to bring Version 19.0 under kerl. But, > problem, I don't know how to decommission the old 19.0 installation. > > Can anyone provide the magic incantation? > > I would probably just uninstall 19.0 from wherever it was installed (i.e. sudo apt remove or whatever the command is for the reverse on a package manager you might have used) and re-build it with kerl. I think this would be easier than figuring out where all the parts are and moving them into kerl. The quickest workaround might also just be to make the kerl paths come before the other ones in your $PATH environment variable, which tends to dictate the lookup order of executables on your filesystem. Regards, Fred. -------------- next part -------------- An HTML attachment was scrubbed... URL: From fly@REDACTED Wed Aug 21 16:34:07 2019 From: fly@REDACTED (Fred Youhanaie) Date: Wed, 21 Aug 2019 15:34:07 +0100 Subject: [erlang-questions] Erlang version confusion In-Reply-To: <1566336590.033616904@apps.rackspace.com> References: <1566336590.033616904@apps.rackspace.com> Message-ID: <13d4070e-1ae8-ad5b-2242-2a7a12c711fc@anydata.co.uk> Hi Lloyd > $ erl > Erlang/OTP 22 [erts-10.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] If you typed this right after kerl install, then 22.0 would have been active. > However, when I try to rebuild my Nitrogen app, it still builds under Erlang Version 19.0. I imagine this was run on a fresh shell session, so 22.0 was no longer active. > Here's kerl status: > > $ kerl status > Available builds: > 21.1,21.1 > 21.1,21.1-builtdocs > 22.0,22.0 > ---------- > Available installations: > 21.1 /home/lloyd/Kerl/21.1 > 22.0 /home/lloyd/Kerl/22.0 > ---------- > No Erlang/OTP installation is currently active To make 22.0 active, use the following source /home/lloyd/Kerl/22.0/activate this should put the 22.0 directories in front of the 19.0 in the environment PATHs use deactivate to undo the above. > Looks like it might be useful to bring Version 19.0 under kerl. But, problem, I don't know how to decommission the old 19.0 installation. See the other Fred's reply :) Cheers, Fred From fly@REDACTED Wed Aug 21 16:38:34 2019 From: fly@REDACTED (Fred Youhanaie) Date: Wed, 21 Aug 2019 15:38:34 +0100 Subject: [erlang-questions] Erlang version confusion In-Reply-To: <13d4070e-1ae8-ad5b-2242-2a7a12c711fc@anydata.co.uk> References: <1566336590.033616904@apps.rackspace.com> <13d4070e-1ae8-ad5b-2242-2a7a12c711fc@anydata.co.uk> Message-ID: <12e7684f-39a1-5598-e450-f051d05b7c1b@anydata.co.uk> On 21/08/2019 15:34, Fred Youhanaie wrote: > > use deactivate to undo the above. Sorry, I meant kerl_deactivate :( From lloyd@REDACTED Wed Aug 21 16:58:31 2019 From: lloyd@REDACTED (Lloyd R. Prentice) Date: Wed, 21 Aug 2019 10:58:31 -0400 Subject: [erlang-questions] Erlang version confusion In-Reply-To: <12e7684f-39a1-5598-e450-f051d05b7c1b@anydata.co.uk> References: <1566336590.033616904@apps.rackspace.com> <13d4070e-1ae8-ad5b-2242-2a7a12c711fc@anydata.co.uk> <12e7684f-39a1-5598-e450-f051d05b7c1b@anydata.co.uk> Message-ID: <64B2F034-F571-47B6-A0E8-BD1BB1633743@writersglen.com> Thanks guys! Lloyd Sent from my iPad > On Aug 21, 2019, at 10:38 AM, Fred Youhanaie wrote: > >> On 21/08/2019 15:34, Fred Youhanaie wrote: >> use deactivate to undo the above. > > Sorry, I meant kerl_deactivate :( > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions From roger@REDACTED Wed Aug 21 17:02:54 2019 From: roger@REDACTED (Roger Lipscombe) Date: Wed, 21 Aug 2019 16:02:54 +0100 Subject: [erlang-questions] ANNOUNCE: blog post about using direnv with kerl (etc.) Message-ID: I was reminded by Lloyd's recent question that I wrote a series of blog posts that might be useful to the Erlang community: http://blog.differentpla.net/blog/2019/01/30/direnv-tool-versions/ It explains how to integrate direnv with kerl and kiex (and nvm, and Python and Ruby) to better manage your Erlang, Elixir (etc.) tool versions. From halostatue@REDACTED Wed Aug 21 17:10:23 2019 From: halostatue@REDACTED (Austin Ziegler) Date: Wed, 21 Aug 2019 11:10:23 -0400 Subject: [erlang-questions] ANNOUNCE: blog post about using direnv with kerl (etc.) In-Reply-To: References: Message-ID: I recently added and extended a couple of recipes to the direnv wiki and it is (mostly) working for me. - My kerl and kiex integrations depend on a couple of utility functions added to your ~/.direnvrc documented here: https://github.com/direnv/direnv/wiki/Find-Up-with-Alternates - I extended the suggestions for kerl here (also added to your ~/.direnvrc): https://github.com/direnv/direnv/wiki/Erlang#automated-fuzzy-erlang-version-switching - I added suggestions for kiex here: https://github.com/direnv/direnv/wiki/Elixir This will allow you to specify a version in your directory as .erlang-version and/or .elixir-version (and to inherit a version from a parent directory). -a On Wed, Aug 21, 2019 at 11:03 AM Roger Lipscombe wrote: > I was reminded by Lloyd's recent question that I wrote a series of > blog posts that might be useful to the Erlang community: > http://blog.differentpla.net/blog/2019/01/30/direnv-tool-versions/ > > It explains how to integrate direnv with kerl and kiex (and nvm, and > Python and Ruby) to better manage your Erlang, Elixir (etc.) tool > versions. > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -- Austin Ziegler ? halostatue@REDACTED ? austin@REDACTED http://www.halostatue.ca/ ? http://twitter.com/halostatue -------------- next part -------------- An HTML attachment was scrubbed... URL: From empro2@REDACTED Wed Aug 21 19:38:33 2019 From: empro2@REDACTED (empro2@REDACTED) Date: Wed, 21 Aug 2019 19:38:33 +0200 Subject: [erlang-questions] Why is <<"Hello">> ++ <<"world!">> a bad idea? Message-ID: <20190821193833.50323ab3@raspy> Playing with bitsy strings I happened to enter s/th like that ? and got a little surprisy. ~Michael -- That which was said, is not that which was spoken, but that which was understood; and none of these comes necessarily close to that which was meant. From raoknz@REDACTED Thu Aug 22 05:58:26 2019 From: raoknz@REDACTED (Richard O'Keefe) Date: Thu, 22 Aug 2019 15:58:26 +1200 Subject: [erlang-questions] Why is <<"Hello">> ++ <<"world!">> a bad idea? In-Reply-To: <20190821193833.50323ab3@raspy> References: <20190821193833.50323ab3@raspy> Message-ID: Because ++ is *list* concatenation and list concatenation only? 1> A = <<"Hello">>, B = <<" ">>, C = <<"world!">>, 1> <>. <<"Hello world!">> On Thu, 22 Aug 2019 at 05:38, wrote: > Playing with bitsy strings I happened to enter s/th like > that ? and got a little surprisy. > > ~Michael > > -- > > That which was said, is not that which was spoken, > but that which was understood; and none of these > comes necessarily close to that which was meant. > > > > > > > > > > > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From areege.alzubaidi@REDACTED Thu Aug 22 15:30:14 2019 From: areege.alzubaidi@REDACTED (Areege Al Zubaidi) Date: Thu, 22 Aug 2019 14:30:14 +0100 Subject: [erlang-questions] Code BEAM is coming to NYC! Get 10% off for a limited time! Message-ID: Hi all! I wanted to reach out and let you know that there?s just a few more days to secure your early bird ticket at Code BEAM Lite NYC ! Early bird training, tutorial, and conference rates end on Monday 26 August! Get 10% off of your tickets before Monday 26 August with the promotional code CBLNYC10! What: Code BEAM Lite NYC 2019 When: 01 October 2019 Where: Bryant Park Ballroom, NYC We have a brilliant lineup of speakers including Bruce Tate, Irina Guberman and experts from Brex, Bloomberg, RabbitMQ, Klarna, and more! Talks include: - Keynote from Bruce Tate, author of Seven languages in seven weeks on the joy of maintaining passion for programming - Keynote from Irina Guberman on the unique resiliency of the BEAM VM - Disruptive credit card provider Brex on their use of Elixir and their approach to microservices - Joseph Yiasemides on Elixir & Go - Brett Cameron on the use of RabbitMQ in the financial industry - Klarna developers Roberto Aloi and Juan Facorro on Rock-solid API with OpenAPI and PropEr - Bloomberg on how RabbitMQ simplifies routing in a microservices architecture - Zsolt Laky on destroying myths and legends on "don?t use open source in a bank" - ? and more ! There are world-class Erlang, Elixir, Phoenix, and RabbitMQ training and tutorials on offer around the conference: * OTP for the seasoned Erlanger by Francesco Cesarini (3-days) * Professional LiveView and OTP by Bruce Tate (3-days) * Crash course in Elixir by Chris Bell (1-day) * RabbitMQ express by Brett Cameron (1-day) * Building resilient distributed systems with Elixir by Chris Keathley (1-day) PS: for our 3-day training courses, buy bundled with a conference ticket to get 10% off! A very limited number of early bird tickets are available, and will close on Monday 26 August at 23:59 EDT! Book now to avoid disappointment! We hope to see you in NYC! Areege -- *Areege Al Zubaidi* *Conferences Marketing Executive* T: +44 (0) 2076550332 W: www.codesync.global A: Erlang Solutions Ltd, The Loom,14 Gower's Walk, London, E1 8PY -- Code Sync & Erlang Solutions Conferences Code BEAM Lite BD - Budapest: 20 September 2019 Code BEAM Lite NYC - NYC: 01 October 2019 Code BEAM Lite - Berlin: 11 October 2019 RabbitMQ Summit - London: 4 November 2019 Code Mesh LDN - London: 7-8 November 2019 Code BEAM Lite India - Bangalore: 14 November 2019 Code BEAM Lite AMS - Amsterdam: 28 November 2019 Lambda Days - Krak?w: 13-14 February 2020 Code BEAM SF - San Francisco: 5-6 March 2020 *Erlang Solutions cares about your data and privacy; please find all details about the basis for communicating with you and the way we process your data in our?**Privacy Policy* *.You can update your email preferences or opt-out from receiving Marketing emails?here .* -------------- next part -------------- An HTML attachment was scrubbed... URL: From bchesneau@REDACTED Fri Aug 23 10:23:47 2019 From: bchesneau@REDACTED (Benoit Chesneau) Date: Fri, 23 Aug 2019 10:23:47 +0200 Subject: [erlang-questions] [ann] French Erlang meetup is back! Message-ID: The Erlang meetup is back!. iIt will take place on 10/09/2019 at Datadog office in common with the Elixir meetup. Registration is here: https://www.meetup.com/Erlang-Paris/events/264213306/ Looking forward to see you there :) Beno?t. -------------- next part -------------- An HTML attachment was scrubbed... URL: From okaprinarjaya@REDACTED Fri Aug 23 14:03:13 2019 From: okaprinarjaya@REDACTED (I Gusti Ngurah Oka Prinarjaya) Date: Fri, 23 Aug 2019 19:03:13 +0700 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? Message-ID: Hi, Now I read Joe's book titled Programming Erlang 2nd Edition. I practice some functions such as for/3, quicksort/1, pythag/1, and perms/1, and perms/1 is the function that hard to understand. I understand comprehension lists, I fully understand for/3, I fully understand quicksort/1, pythag/1. But it's really hard for me to understand perms/1. Please teach me how to read and understand this perms/1 function. perms([]) -> [[]]; perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. Output: 1> lib_misc:perms("123"). ["123","132","213","231","312","321"] Please enlightenment Thank you -------------- next part -------------- An HTML attachment was scrubbed... URL: From oliver.bollmann@REDACTED Fri Aug 23 14:17:58 2019 From: oliver.bollmann@REDACTED (Oliver Bollmann) Date: Fri, 23 Aug 2019 14:17:58 +0200 Subject: [erlang-questions] ssl {reuse_sessions,false} Message-ID: Hi, we have 5000 clients(third party) connecting each 25 seconds to our server over tls 1.2, 24h later the table server_ssl_opt_session_cache has about? 18 million objects and allocate 5GByte! If we use {reuse_sessions,false} the table(server_ssl_opt_session_cache) is not empty! Any hints? -- Gr??e Oliver Bollmann From ingela.andin@REDACTED Fri Aug 23 14:52:48 2019 From: ingela.andin@REDACTED (Ingela Andin) Date: Fri, 23 Aug 2019 14:52:48 +0200 Subject: [erlang-questions] ssl {reuse_sessions,false} In-Reply-To: References: Message-ID: Hi! {reuse_sessions,false} just makes the current connection not use the feature but the information is saved for possible other connections to use it, as it is configured per connection and the ssl application can not know if might need it later. Since ssl-8.2.1 there should be a working limitation of the table, although it is a soft limit due to current implementation trade offs, and it will be shrieked gradually. At a very high load it might shrink to slow, the workaround would be to have a callback for the session table that does not save the information. We been thinking about changing the implementation but TLS-1.3 has a new mechanism, and there is also other mechanisms for TLS 1.2 the we have not implemented so it just have not landed in best way forward yet. Regards Ingela - Erlang/OTP Team - Ericsson AB Den fre 23 aug. 2019 kl 14:18 skrev Oliver Bollmann < oliver.bollmann@REDACTED>: > Hi, > > we have 5000 clients(third party) connecting each 25 seconds to our > server over tls 1.2, > > 24h later the table server_ssl_opt_session_cache has about 18 million > objects and allocate 5GByte! > > If we use {reuse_sessions,false} the table(server_ssl_opt_session_cache) > is not empty! > > Any hints? > > -- > Gr??e > Oliver Bollmann > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From oliver.bollmann@REDACTED Fri Aug 23 15:31:11 2019 From: oliver.bollmann@REDACTED (Oliver Bollmann) Date: Fri, 23 Aug 2019 15:31:11 +0200 Subject: [erlang-questions] ssl {reuse_sessions,false} In-Reply-To: References: Message-ID: -ssl session_lifetime 120; each 2 minutes will delete sessions from server_ssl_opt_session_cache Right? Oliver On 23.08.19 14:52, Ingela Andin wrote: > Hi! > > {reuse_sessions,false} just makes the current connection not use the > feature but the information is > saved for possible other connections to use it, as it is configured > per connection and the ssl application can not know > if might need it later. > > Since ssl-8.2.1 there should be a working limitation of the table, > although it is a soft limit due to current implementation trade offs, > and it will be shrieked gradually. At a very high load it might shrink > to slow, the workaround would be to have a callback for the session > table that does not save the information. > > We been thinking about changing the implementation but TLS-1.3 has a > new mechanism, and there is also other mechanisms for TLS 1.2 the we > have not implemented so it just have not landed in best way forward yet. > > Regards Ingela - Erlang/OTP Team - Ericsson AB > > > > > > > Den fre 23 aug. 2019 kl 14:18 skrev Oliver Bollmann > >: > > Hi, > > we have 5000 clients(third party) connecting each 25 seconds to our > server over tls 1.2, > > 24h later the table server_ssl_opt_session_cache has about 18 million > objects and allocate 5GByte! > > If we use {reuse_sessions,false} the > table(server_ssl_opt_session_cache) > is not empty! > > Any hints? > > -- > Gr??e > Oliver Bollmann > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -- Gr??e Oliver Bollmann -------------- next part -------------- An HTML attachment was scrubbed... URL: From fly@REDACTED Fri Aug 23 15:37:56 2019 From: fly@REDACTED (Fred Youhanaie) Date: Fri, 23 Aug 2019 14:37:56 +0100 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: References: Message-ID: <146ad5d9-039a-a367-e8b8-ae6c9466f68d@anydata.co.uk> Hi Try expanding it by hand with shorter lists, i.e. perms("1") and perms("12") To start you off, and using [a, b, c], instead of "123" perms([a]) = [ [H|T] || H <- [a], T <- perms([a]--H) ] = [ [a | T] T <- perms([a]--[a])] %% replace H, one item = [ [a | T] T <- perms([])] ] = [ [a | T] T <- [[]] ] %% replace T = [ [a | []] ] = [ [a] ] perms([a, b]) = [ [H|T] || H <- [a, b], T <- perms([a, b]--H) ] = [ [a|T] || T <- perms([b]), [b|T] || T <- perms([a]) ] %% replace H, two items = [ [a|T] || T <- [[b]], [b|T] || T <- [[a]] ] = ... I'll let you complete the rest yourself ;-) HTH Cheers, Fred On 23/08/2019 13:03, I Gusti Ngurah Oka Prinarjaya wrote: > Hi, > > Now I read Joe's book titled Programming Erlang 2nd Edition. I practice some functions such as for/3, quicksort/1, pythag/1, and perms/1, and perms/1 is the function that hard to understand. > > I understand comprehension lists, I fully understand for/3, I fully understand quicksort/1, pythag/1. But it's really hard for me to understand perms/1. Please teach me how to read and understand this > perms/1 function. > > perms([]) -> [[]]; > perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. > > Output: > 1> lib_misc:perms("123"). > n > > Please enlightenment > > Thank you > > > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > From sverker@REDACTED Fri Aug 23 15:44:02 2019 From: sverker@REDACTED (Sverker Eriksson) Date: Fri, 23 Aug 2019 15:44:02 +0200 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: References: Message-ID: <1566567842.23297.21.camel@erlang.org> How to create all permutations of List: ? Construct all possible lists [H|T] ? ? where H is one element of List ? ? and T is one of all the permutations of the remaining elements in List. And the empty list has one permutation; the empty list. /Sverker On fre, 2019-08-23 at 19:03 +0700, I Gusti Ngurah Oka Prinarjaya wrote: > Hi, > > Now I read Joe's book titled Programming Erlang 2nd Edition. I practice some > functions such as for/3, quicksort/1, pythag/1, and perms/1, and perms/1 is > the function that hard to understand. > > I understand comprehension lists, I fully understand for/3, I fully understand > quicksort/1, pythag/1. But it's really hard for me to understand perms/1. > Please teach me how to read and understand this perms/1 function. > > perms([]) -> [[]]; > perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. > > Output: > 1> lib_misc:perms("123"). > ["123","132","213","231","312","321"] > > Please enlightenment > > Thank you > > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > https://protect2.fireeye.com/url?k=39e8964b-6562b484-39e8d6d0-0cc47ad93ea4-789 > 7557dbe1f450b&q=1&u=http%3A%2F%2Ferlang.org%2Fmailman%2Flistinfo%2Ferlang- > questions From jesper.louis.andersen@REDACTED Fri Aug 23 15:47:03 2019 From: jesper.louis.andersen@REDACTED (Jesper Louis Andersen) Date: Fri, 23 Aug 2019 15:47:03 +0200 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: References: Message-ID: On Fri, Aug 23, 2019 at 2:03 PM I Gusti Ngurah Oka Prinarjaya < okaprinarjaya@REDACTED> wrote: > Hi, > > Now I read Joe's book titled Programming Erlang 2nd Edition. I practice > some functions such as for/3, quicksort/1, pythag/1, and perms/1, and > perms/1 is the function that hard to understand. > > I understand comprehension lists, I fully understand for/3, I fully > understand quicksort/1, pythag/1. But it's really hard for me to understand > perms/1. Please teach me how to read and understand this perms/1 function. > > perms([]) -> [[]]; > perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. > > Note you have two generators in the comprehension. So for each generated H, it generates all the possible T's. Also note that the T's depend on the H. It is akin to having a for-loop within a for-loop: for H := range(List) { for T := perms(List -- [H]) { Res := append(Res, [H|T]) } } Now, to understand why this works, the argument is based on an induction principle: Observe that to generate a permutation, you first select something which goes first, H, and then you need to generate a permutation out of the remaining elements, List -- [H]. Suppose we fix H to some value in the list. Then surely, we can generate all the permutations where H goes first, by generating perms(List - [H]) and then attaching H to all the results: perms(List) -> H = pick_among(List), [ [H|T] || T <- perms(List -- [H]) ]. But now note that to generate all permutations, any element could have been picked by pick_among/1. So we need to loop over all elements in the list one at a time, and consider what happens if that element goes first. This is what the original code is doing. Alternative wordings by Sverker and Fred :) -------------- next part -------------- An HTML attachment was scrubbed... URL: From elbrujohalcon@REDACTED Fri Aug 23 16:09:42 2019 From: elbrujohalcon@REDACTED (Brujo Benavides) Date: Fri, 23 Aug 2019 11:09:42 -0300 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: References: Message-ID: <30987D7F-64D6-4762-96BD-A7E92769C595@gmail.com> Since I needed a bit more space to write an answer ?? I replied on my blog ?? Cheers :) Brujo Benavides > On 23 Aug 2019, at 10:47, Jesper Louis Andersen wrote: > > On Fri, Aug 23, 2019 at 2:03 PM I Gusti Ngurah Oka Prinarjaya > wrote: > Hi, > > Now I read Joe's book titled Programming Erlang 2nd Edition. I practice some functions such as for/3, quicksort/1, pythag/1, and perms/1, and perms/1 is the function that hard to understand. > > I understand comprehension lists, I fully understand for/3, I fully understand quicksort/1, pythag/1. But it's really hard for me to understand perms/1. Please teach me how to read and understand this perms/1 function. > > perms([]) -> [[]]; > perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. > > > Note you have two generators in the comprehension. So for each generated H, it generates all the possible T's. Also note that the T's depend on the H. It is akin to having a for-loop within a for-loop: > > for H := range(List) { > for T := perms(List -- [H]) { > Res := append(Res, [H|T]) > } > } > > Now, to understand why this works, the argument is based on an induction principle: > > Observe that to generate a permutation, you first select something which goes first, H, and then you need to generate a permutation out of the remaining elements, List -- [H]. Suppose we fix H to some value in the list. Then surely, we can generate all the permutations where H goes first, by generating perms(List - [H]) and then attaching H to all the results: > > perms(List) -> > H = pick_among(List), > [ [H|T] || T <- perms(List -- [H]) ]. > > But now note that to generate all permutations, any element could have been picked by pick_among/1. So we need to loop over all elements in the list one at a time, and consider what happens if that element goes first. This is what the original code is doing. > > Alternative wordings by Sverker and Fred :) > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions -------------- next part -------------- An HTML attachment was scrubbed... URL: From okaprinarjaya@REDACTED Fri Aug 23 16:15:56 2019 From: okaprinarjaya@REDACTED (I Gusti Ngurah Oka Prinarjaya) Date: Fri, 23 Aug 2019 21:15:56 +0700 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: References: Message-ID: Hi Folks, Wowwwwww... thank you very much for your attention guys. Thank you very much for all of your answers, then now is my turn to make practice based on all of the answers. Thank you all. I hope i can grok how this code works Pada tanggal Jum, 23 Agt 2019 20.47, Jesper Louis Andersen < jesper.louis.andersen@REDACTED> menulis: > On Fri, Aug 23, 2019 at 2:03 PM I Gusti Ngurah Oka Prinarjaya < > okaprinarjaya@REDACTED> wrote: > >> Hi, >> >> Now I read Joe's book titled Programming Erlang 2nd Edition. I practice >> some functions such as for/3, quicksort/1, pythag/1, and perms/1, and >> perms/1 is the function that hard to understand. >> >> I understand comprehension lists, I fully understand for/3, I fully >> understand quicksort/1, pythag/1. But it's really hard for me to understand >> perms/1. Please teach me how to read and understand this perms/1 >> function. >> >> perms([]) -> [[]]; >> perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. >> >> > Note you have two generators in the comprehension. So for each generated > H, it generates all the possible T's. Also note that the T's depend on the > H. It is akin to having a for-loop within a for-loop: > > for H := range(List) { > for T := perms(List -- [H]) { > Res := append(Res, [H|T]) > } > } > > Now, to understand why this works, the argument is based on an induction > principle: > > Observe that to generate a permutation, you first select something which > goes first, H, and then you need to generate a permutation out of the > remaining elements, List -- [H]. Suppose we fix H to some value in the > list. Then surely, we can generate all the permutations where H goes first, > by generating perms(List - [H]) and then attaching H to all the results: > > perms(List) -> > H = pick_among(List), > [ [H|T] || T <- perms(List -- [H]) ]. > > But now note that to generate all permutations, any element could have > been picked by pick_among/1. So we need to loop over all elements in the > list one at a time, and consider what happens if that element goes first. > This is what the original code is doing. > > Alternative wordings by Sverker and Fred :) > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From okaprinarjaya@REDACTED Fri Aug 23 16:35:38 2019 From: okaprinarjaya@REDACTED (I Gusti Ngurah Oka Prinarjaya) Date: Fri, 23 Aug 2019 21:35:38 +0700 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: References: Message-ID: Thank you @Brujo Benavides, i will read your blog. Pada tanggal Jum, 23 Agu 2019 pukul 21.15 I Gusti Ngurah Oka Prinarjaya < okaprinarjaya@REDACTED> menulis: > Hi Folks, > > Wowwwwww... thank you very much for your attention guys. > > Thank you very much for all of your answers, then now is my turn to make > practice based on all of the answers. > > Thank you all. I hope i can grok how this code works > > > > > Pada tanggal Jum, 23 Agt 2019 20.47, Jesper Louis Andersen < > jesper.louis.andersen@REDACTED> menulis: > >> On Fri, Aug 23, 2019 at 2:03 PM I Gusti Ngurah Oka Prinarjaya < >> okaprinarjaya@REDACTED> wrote: >> >>> Hi, >>> >>> Now I read Joe's book titled Programming Erlang 2nd Edition. I practice >>> some functions such as for/3, quicksort/1, pythag/1, and perms/1, and >>> perms/1 is the function that hard to understand. >>> >>> I understand comprehension lists, I fully understand for/3, I fully >>> understand quicksort/1, pythag/1. But it's really hard for me to understand >>> perms/1. Please teach me how to read and understand this perms/1 >>> function. >>> >>> perms([]) -> [[]]; >>> perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. >>> >>> >> Note you have two generators in the comprehension. So for each generated >> H, it generates all the possible T's. Also note that the T's depend on the >> H. It is akin to having a for-loop within a for-loop: >> >> for H := range(List) { >> for T := perms(List -- [H]) { >> Res := append(Res, [H|T]) >> } >> } >> >> Now, to understand why this works, the argument is based on an induction >> principle: >> >> Observe that to generate a permutation, you first select something which >> goes first, H, and then you need to generate a permutation out of the >> remaining elements, List -- [H]. Suppose we fix H to some value in the >> list. Then surely, we can generate all the permutations where H goes first, >> by generating perms(List - [H]) and then attaching H to all the results: >> >> perms(List) -> >> H = pick_among(List), >> [ [H|T] || T <- perms(List -- [H]) ]. >> >> But now note that to generate all permutations, any element could have >> been picked by pick_among/1. So we need to loop over all elements in the >> list one at a time, and consider what happens if that element goes first. >> This is what the original code is doing. >> >> Alternative wordings by Sverker and Fred :) >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From eckard.brauer@REDACTED Fri Aug 23 16:38:47 2019 From: eckard.brauer@REDACTED (Eckard Brauer) Date: Fri, 23 Aug 2019 16:38:47 +0200 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: <30987D7F-64D6-4762-96BD-A7E92769C595@gmail.com> References: <30987D7F-64D6-4762-96BD-A7E92769C595@gmail.com> Message-ID: <20190823163847.4ea37d7e@gmx.de> Nice explanation, thank you! For me, it helps to think of mathematical induction: First trying to get a model of the base case(s) - occasionally more than only one exist. After that I (try to) think of the step case - how to evolve from base or any given case to the next (more complex) one. The brilliance of the example is to show multiple conditions - one for head, one (dependent) for tail - are given the probably elegantest possible way. Eckard Am Fri, 23 Aug 2019 11:09:42 -0300 schrieb Brujo Benavides : > Since I needed a bit more space to write an answer ?? I replied on my > blog > > ?? Cheers :) > > Brujo Benavides > > > > > On 23 Aug 2019, at 10:47, Jesper Louis Andersen > > wrote: > > > > On Fri, Aug 23, 2019 at 2:03 PM I Gusti Ngurah Oka Prinarjaya > > > wrote: > > Hi, > > > > Now I read Joe's book titled Programming Erlang 2nd Edition. I > > practice some functions such as for/3, quicksort/1, pythag/1, and > > perms/1, and perms/1 is the function that hard to understand. > > > > I understand comprehension lists, I fully understand for/3, I fully > > understand quicksort/1, pythag/1. But it's really hard for me to > > understand perms/1. Please teach me how to read and understand this > > perms/1 function. > > > > perms([]) -> [[]]; > > perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. > > > > > > Note you have two generators in the comprehension. So for each > > generated H, it generates all the possible T's. Also note that the > > T's depend on the H. It is akin to having a for-loop within a > > for-loop: > > > > for H := range(List) { > > for T := perms(List -- [H]) { > > Res := append(Res, [H|T]) > > } > > } > > > > Now, to understand why this works, the argument is based on an > > induction principle: > > > > Observe that to generate a permutation, you first select something > > which goes first, H, and then you need to generate a permutation > > out of the remaining elements, List -- [H]. Suppose we fix H to > > some value in the list. Then surely, we can generate all the > > permutations where H goes first, by generating perms(List - [H]) > > and then attaching H to all the results: > > > > perms(List) -> > > H = pick_among(List), > > [ [H|T] || T <- perms(List -- [H]) ]. > > > > But now note that to generate all permutations, any element could > > have been picked by pick_among/1. So we need to loop over all > > elements in the list one at a time, and consider what happens if > > that element goes first. This is what the original code is doing. > > > > Alternative wordings by Sverker and Fred :) > > > > _______________________________________________ > > erlang-questions mailing list > > erlang-questions@REDACTED > > http://erlang.org/mailman/listinfo/erlang-questions > -- Wir haften nicht f?r die korrekte Funktion der in dieser eMail enthaltenen Viren. We are not liable for correct function of the viruses in this email! :) -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 195 bytes Desc: Digitale Signatur von OpenPGP URL: From okaprinarjaya@REDACTED Fri Aug 23 17:02:52 2019 From: okaprinarjaya@REDACTED (I Gusti Ngurah Oka Prinarjaya) Date: Fri, 23 Aug 2019 22:02:52 +0700 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: <20190823163847.4ea37d7e@gmx.de> References: <30987D7F-64D6-4762-96BD-A7E92769C595@gmail.com> <20190823163847.4ea37d7e@gmx.de> Message-ID: Hi, Wow.. after reading the blog's introduction, i realize, it turns out a very special beautiful function and it turns out R. Virding is a fans of this looks-simple-and-beautiful function hahaha. Wow it's amazing and looks great for me. Thank you Pada tanggal Jum, 23 Agu 2019 pukul 21.39 Eckard Brauer < eckard.brauer@REDACTED> menulis: > Nice explanation, thank you! > > For me, it helps to think of mathematical induction: > > First trying to get a model of the base case(s) - occasionally more > than only one exist. > > After that I (try to) think of the step case - how to evolve from base > or any given case to the next (more complex) one. > > The brilliance of the example is to show multiple conditions - one for > head, one (dependent) for tail - are given the probably elegantest > possible way. > > Eckard > > Am Fri, 23 Aug 2019 11:09:42 -0300 > schrieb Brujo Benavides : > > > Since I needed a bit more space to write an answer ?? I replied on my > > blog > > < > https://medium.com/erlang-battleground/how-to-comprehend-comprehensions-c924f92a97e1?sk=b668da926f05b7293f34dafa48fa5654 > > > > ?? Cheers :) > > > > Brujo Benavides > > > > > > > > > On 23 Aug 2019, at 10:47, Jesper Louis Andersen > > > wrote: > > > > > > On Fri, Aug 23, 2019 at 2:03 PM I Gusti Ngurah Oka Prinarjaya > > > > wrote: > > > Hi, > > > > > > Now I read Joe's book titled Programming Erlang 2nd Edition. I > > > practice some functions such as for/3, quicksort/1, pythag/1, and > > > perms/1, and perms/1 is the function that hard to understand. > > > > > > I understand comprehension lists, I fully understand for/3, I fully > > > understand quicksort/1, pythag/1. But it's really hard for me to > > > understand perms/1. Please teach me how to read and understand this > > > perms/1 function. > > > > > > perms([]) -> [[]]; > > > perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. > > > > > > > > > Note you have two generators in the comprehension. So for each > > > generated H, it generates all the possible T's. Also note that the > > > T's depend on the H. It is akin to having a for-loop within a > > > for-loop: > > > > > > for H := range(List) { > > > for T := perms(List -- [H]) { > > > Res := append(Res, [H|T]) > > > } > > > } > > > > > > Now, to understand why this works, the argument is based on an > > > induction principle: > > > > > > Observe that to generate a permutation, you first select something > > > which goes first, H, and then you need to generate a permutation > > > out of the remaining elements, List -- [H]. Suppose we fix H to > > > some value in the list. Then surely, we can generate all the > > > permutations where H goes first, by generating perms(List - [H]) > > > and then attaching H to all the results: > > > > > > perms(List) -> > > > H = pick_among(List), > > > [ [H|T] || T <- perms(List -- [H]) ]. > > > > > > But now note that to generate all permutations, any element could > > > have been picked by pick_among/1. So we need to loop over all > > > elements in the list one at a time, and consider what happens if > > > that element goes first. This is what the original code is doing. > > > > > > Alternative wordings by Sverker and Fred :) > > > > > > _______________________________________________ > > > erlang-questions mailing list > > > erlang-questions@REDACTED > > > http://erlang.org/mailman/listinfo/erlang-questions > > > > > > -- > Wir haften nicht f?r die korrekte Funktion der in dieser eMail > enthaltenen Viren. We are not liable for correct function of the > viruses in this email! :) > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ingela.andin@REDACTED Fri Aug 23 17:36:46 2019 From: ingela.andin@REDACTED (Ingela Andin) Date: Fri, 23 Aug 2019 17:36:46 +0200 Subject: [erlang-questions] ssl {reuse_sessions,false} In-Reply-To: References: Message-ID: Yes it will, there is also: *session_cache_client_max = integer() * Limits the growth of the clients session cache, that is how many sessions towards servers that are cached to be used by new client connections. If the maximum number of sessions is reached, the current cache entries will be invalidated regardless of their remaining lifetime. Defaults to 1000. Recommended ssl-8.2.1 or later for this option to work as intended. * session_cache_server_max = integer() * Limits the growth of the servers session cache, that is how many client sessions are cached by the server. If the maximum number of sessions is reached, the current cache entries will be invalidated regardless of their remaining lifetime. Defaults to 1000. Recommended ssl-8.2.1 or later for this option to work as intended. Regards Ingela Den fre 23 aug. 2019 kl 15:31 skrev Oliver Bollmann < oliver.bollmann@REDACTED>: > -ssl session_lifetime 120; each 2 minutes > > will delete sessions from server_ssl_opt_session_cache > > Right? > > Oliver > > On 23.08.19 14:52, Ingela Andin wrote: > > Hi! > > {reuse_sessions,false} just makes the current connection not use the > feature but the information is > saved for possible other connections to use it, as it is configured per > connection and the ssl application can not know > if might need it later. > > Since ssl-8.2.1 there should be a working limitation of the table, > although it is a soft limit due to current implementation trade offs, and > it will be shrieked gradually. At a very high load it might shrink to slow, > the workaround would be to have a callback for the session table that does > not save the information. > > We been thinking about changing the implementation but TLS-1.3 has a new > mechanism, and there is also other mechanisms for TLS 1.2 the we have not > implemented so it just have not landed in best way forward yet. > > Regards Ingela - Erlang/OTP Team - Ericsson AB > > > > > > > Den fre 23 aug. 2019 kl 14:18 skrev Oliver Bollmann < > oliver.bollmann@REDACTED>: > >> Hi, >> >> we have 5000 clients(third party) connecting each 25 seconds to our >> server over tls 1.2, >> >> 24h later the table server_ssl_opt_session_cache has about 18 million >> objects and allocate 5GByte! >> >> If we use {reuse_sessions,false} the table(server_ssl_opt_session_cache) >> is not empty! >> >> Any hints? >> >> -- >> Gr??e >> Oliver Bollmann >> >> _______________________________________________ >> erlang-questions mailing list >> erlang-questions@REDACTED >> http://erlang.org/mailman/listinfo/erlang-questions >> > -- > Gr??e > Oliver Bollmann > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From empro2@REDACTED Fri Aug 23 17:52:24 2019 From: empro2@REDACTED (empro2@REDACTED) Date: Fri, 23 Aug 2019 17:52:24 +0200 Subject: [erlang-questions] Stop Emacs erlang shell from echoing? Message-ID: <20190823175224.44c7f540@raspy> comint-process-echoes is nil so erlang.el seems to decide not to setq although: * system-type is 'gnu/linux' * inf...type is 'newshell' So says F1 v ... with shell buffer focussed, but this snippet from erlang.el seems to disagree: ``` (if (and (not (eq system-type 'windows-nt)) (eq inferior-erlang-shell-type 'newshell)) (setq comint-process-echoes t)) ``` The buffer was raised by compiling some of my Erlang drivel. I did M-x set-variable it to t and the echo went away. I think I can stuff some ``` (add-hook 'erlang-shell-mode-hook (lambda () (setq comint-process-echoes t))) ``` into my init.el, but that might simply cover up something that is not the way it is supposed to be ? and which I do not understand. There also might be a good reason not to have the echoes deleted? Michael -- If a bank in need of money is systematically important, then that system is not important. From okaprinarjaya@REDACTED Sat Aug 24 21:23:05 2019 From: okaprinarjaya@REDACTED (I Gusti Ngurah Oka Prinarjaya) Date: Sun, 25 Aug 2019 02:23:05 +0700 Subject: [erlang-questions] How to understanding recursive inside comprehension lists? In-Reply-To: References: <30987D7F-64D6-4762-96BD-A7E92769C595@gmail.com> <20190823163847.4ea37d7e@gmx.de> Message-ID: Hi, Hi @Brujo Benavides. Some of the code cannot work in my machine, returning weird / not valid return result. 1. This code: perms3([]) -> [[]]; perms3(List) -> [ perms3(List -- [H]) || H <- List ]. Output: perms3("abc"). [[[[[]]],[[[]]]],[[[[]]],[[[]]]],[[[[]]],[[[]]]]] 2. This code: perms4([]) -> [[]]; perms4(List) -> [T || H <- List, T <- perms4(List -- [H]). Output: perms4("abc"). [[],[],[],[],[],[]] This is detail of my erlang version in Mac machine Erlang/OTP 21 [erts-10.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] Eshell V10.3 (abort with ^G) Thank you Pada tanggal Jum, 23 Agu 2019 pukul 22.02 I Gusti Ngurah Oka Prinarjaya < okaprinarjaya@REDACTED> menulis: > Hi, > > Wow.. after reading the blog's introduction, i realize, it turns out a > very special beautiful function and it turns out R. Virding is a fans of > this looks-simple-and-beautiful function hahaha. Wow it's amazing and looks > great for me. > > Thank you > > > > > Pada tanggal Jum, 23 Agu 2019 pukul 21.39 Eckard Brauer < > eckard.brauer@REDACTED> menulis: > >> Nice explanation, thank you! >> >> For me, it helps to think of mathematical induction: >> >> First trying to get a model of the base case(s) - occasionally more >> than only one exist. >> >> After that I (try to) think of the step case - how to evolve from base >> or any given case to the next (more complex) one. >> >> The brilliance of the example is to show multiple conditions - one for >> head, one (dependent) for tail - are given the probably elegantest >> possible way. >> >> Eckard >> >> Am Fri, 23 Aug 2019 11:09:42 -0300 >> schrieb Brujo Benavides : >> >> > Since I needed a bit more space to write an answer ?? I replied on my >> > blog >> > < >> https://medium.com/erlang-battleground/how-to-comprehend-comprehensions-c924f92a97e1?sk=b668da926f05b7293f34dafa48fa5654 >> > >> > ?? Cheers :) >> > >> > Brujo Benavides >> > >> > >> > >> > > On 23 Aug 2019, at 10:47, Jesper Louis Andersen >> > > wrote: >> > > >> > > On Fri, Aug 23, 2019 at 2:03 PM I Gusti Ngurah Oka Prinarjaya >> > > > wrote: >> > > Hi, >> > > >> > > Now I read Joe's book titled Programming Erlang 2nd Edition. I >> > > practice some functions such as for/3, quicksort/1, pythag/1, and >> > > perms/1, and perms/1 is the function that hard to understand. >> > > >> > > I understand comprehension lists, I fully understand for/3, I fully >> > > understand quicksort/1, pythag/1. But it's really hard for me to >> > > understand perms/1. Please teach me how to read and understand this >> > > perms/1 function. >> > > >> > > perms([]) -> [[]]; >> > > perms(List) -> [ [H|T] || H <- List, T <- perms(List--[H]) ]. >> > > >> > > >> > > Note you have two generators in the comprehension. So for each >> > > generated H, it generates all the possible T's. Also note that the >> > > T's depend on the H. It is akin to having a for-loop within a >> > > for-loop: >> > > >> > > for H := range(List) { >> > > for T := perms(List -- [H]) { >> > > Res := append(Res, [H|T]) >> > > } >> > > } >> > > >> > > Now, to understand why this works, the argument is based on an >> > > induction principle: >> > > >> > > Observe that to generate a permutation, you first select something >> > > which goes first, H, and then you need to generate a permutation >> > > out of the remaining elements, List -- [H]. Suppose we fix H to >> > > some value in the list. Then surely, we can generate all the >> > > permutations where H goes first, by generating perms(List - [H]) >> > > and then attaching H to all the results: >> > > >> > > perms(List) -> >> > > H = pick_among(List), >> > > [ [H|T] || T <- perms(List -- [H]) ]. >> > > >> > > But now note that to generate all permutations, any element could >> > > have been picked by pick_among/1. So we need to loop over all >> > > elements in the list one at a time, and consider what happens if >> > > that element goes first. This is what the original code is doing. >> > > >> > > Alternative wordings by Sverker and Fred :) >> > > >> > > _______________________________________________ >> > > erlang-questions mailing list >> > > erlang-questions@REDACTED >> > > http://erlang.org/mailman/listinfo/erlang-questions >> > >> >> >> >> -- >> Wir haften nicht f?r die korrekte Funktion der in dieser eMail >> enthaltenen Viren. We are not liable for correct function of the >> viruses in this email! :) >> _______________________________________________ >> erlang-questions mailing list >> erlang-questions@REDACTED >> http://erlang.org/mailman/listinfo/erlang-questions >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From publicityifl@REDACTED Mon Aug 26 16:28:21 2019 From: publicityifl@REDACTED (Jurriaan Hage) Date: Mon, 26 Aug 2019 07:28:21 -0700 Subject: [erlang-questions] First call for participation for IFL 2019 (Implementation and Application of Functional Languages) Message-ID: Hello, Please, find below the first call for participation for IFL 2019. Please forward these to anyone you think may be interested. Apologies for any duplicates you may receive. best regards, Jurriaan Hage Publicity Chair of IFL ================================================================================ IFL 2019 31st Symposium on Implementation and Application of Functional Languages National University of Singapore September 25th-27th, 2019 http://2019.iflconference.org ================================================================================ ### Scope The goal of the IFL symposia is to bring together researchers actively engaged in the implementation and application of functional and function-based programming languages. IFL 2019 will be a venue for researchers to present and discuss new ideas and concepts, work in progress, and publication-ripe results related to the implementation and application of functional languages and function-based programming. Topics of interest to IFL include, but are not limited to: - language concepts - type systems, type checking, type inferencing - compilation techniques - staged compilation - run-time function specialization - run-time code generation - partial evaluation - (abstract) interpretation - metaprogramming - generic programming - automatic program generation - array processing - concurrent/parallel programming - concurrent/parallel program execution - embedded systems - web applications - (embedded) domain specific languages - security - novel memory management techniques - run-time profiling performance measurements - debugging and tracing - virtual/abstract machine architectures - validation, verification of functional programs - tools and programming techniques - (industrial) applications ### Keynote Speaker * Olivier Danvy, Yale-NUS College ### Submissions and peer-review Differently from previous editions of IFL, IFL 2019 solicits two kinds of submissions: * Regular papers (12 pages including references) * Draft papers for presentations ('weak' limit between 8 and 15 pages) Regular papers will undergo a rigorous review by the program committee, and will be evaluated according to their correctness, novelty, originality, relevance, significance, and clarity. A set of regular papers will be conditionally accepted for publication. Authors of conditionally accepted papers will be provided with committee reviews along with a set of mandatory revisions. Regular papers not accepted for publication will be considered as draft papers, at the request of the author. Draft papers will be screened to make sure that they are within the scope of IFL, and will be accepted for presentation or rejected accordingly. Prior to the symposium: Authors of conditionally accepted papers and accepted presentations will submit a pre-proceedings version of their work that will appear in the draft proceedings distributed at the symposium. The draft proceedings does not constitute a formal publication. We require that at least one of the authors present the work at IFL 2019. After the symposium: Authors of conditionally accepted papers will submit a revised versions of their paper for the formal post-proceedings. The program committee will assess whether the mandatory revisions have been adequately addressed by the authors and thereby determines the final accept/reject status of the paper. Our interest is to ultimately accept all conditionally accepted papers. If you are an author of a conditionally accepted paper, please make sure that you address all the concerns of the reviewers. Authors of accepted presentations will be given the opportunity to incorporate the feedback from discussions at the symposium and will be invited to submit a revised full article for the formal post-proceedings. The program committee will evaluate these submissions according to their correctness, novelty, originality, relevance, significance, and clarity, and will thereby determine whether the paper is accepted or rejected. ### Publication The formal proceedings will appear in the International Conference Proceedings Series of the ACM Digital Library. At no time may work submitted to IFL be simultaneously submitted to other venues; submissions must adhere to ACM SIGPLAN's republication policy: http://www.sigplan.org/Resources/Policies/Republication ### Important dates Submission of regular papers: June 15, 2019 Submission of draft papers: August 1, 2019 Regular papers notification: August 1, 2019 Regular draft papers notification: August 7, 2019 Deadline for early registration: August 31, 2019 Submission of pre-proceedings version: September 15, 2019 IFL Symposium: September 25-27, 2019 Submission of papers for post-proceedings: November 30, 2019 Notification of acceptance: January 31, 2020 Camera-ready version: February 29, 2020 ### Submission details All contributions must be written in English. Papers must use the ACM two columns conference format, which can be found at: http://www.acm.org/publications/proceedings-template Authors submit through EasyChair: https://easychair.org/conferences/?conf=ifl2019 ### Peter Landin Prize The Peter Landin Prize is awarded to the best paper presented at the symposium every year. The honored article is selected by the program committee based on the submissions received for the formal review process. The prize carries a cash award equivalent to 150 Euros. ### Organization and Program committee Chairs: Jurrien Stutterheim (Standard Chartered Bank Singapore), Wei Ngan Chin (National University of Singapore) Program Committee: - Olaf Chitil, University of Kent - Clemens Grelck, University of Amsterdam - Daisuke Kimura, Toho University - Pieter Koopman, Radboud University - Tam?s Kozsik, E?tv?s Lor?nd University - Roman Leschinskiy, Facebook - Ben Lippmeier, The University of New South Wales - Marco T. Morazan, Seton Hall University - Sven-Bodo Scholz, Heriot-Watt University - Tom Schrijvers, Katholieke Universiteit Leuven - Alejandro Serrano, Utrecht University - Tony Sloane, Macquarie University - Simon Thompson, University of Kent - Marcos Viera, Universidad de la Rep?blica - Wei Ngan Chin, NUS - Jurri?n Stutterheim, Standard Chartered Bank ### Venue The 31st IFL is organized by the National University of Singapore. Singapore is located in the heart of South-East Asia, and the city itself is extremely well connected by trains and taxis. See the website for more information on the venue. ### Acknowledgments This call-for-papers is an adaptation and evolution of content from previous instances of IFL. We are grateful to prior organizers for their work, which is reused here. A part of IFL 2019 format and CFP language that describes conditionally accepted papers has been adapted from call-for-papers of OOPSLA conferences. -------------- next part -------------- An HTML attachment was scrubbed... URL: From bchesneau@REDACTED Mon Aug 26 23:41:15 2019 From: bchesneau@REDACTED (Benoit Chesneau) Date: Mon, 26 Aug 2019 23:41:15 +0200 Subject: [erlang-questions] [ann] erlang-rocksdb version 1.3 has been released Message-ID: A quick mail to announce I just published erlang-rocksdb version 1.3, a binding of RocksDB for applications based on Erlang (including Elixir and others languages on top of the VM). This release brings the support of windows, new version 6.2.2 of rocksdb and some other fixes. Mor info about the release on Gitlab: https://gitlab.com/barrel-db/erlang-rocksdb To get started: https://gitlab.com/barrel-db/erlang-rocksdb Enjoy! Beno?t -------------- next part -------------- An HTML attachment was scrubbed... URL: From okaprinarjaya@REDACTED Wed Aug 28 06:41:01 2019 From: okaprinarjaya@REDACTED (I Gusti Ngurah Oka Prinarjaya) Date: Wed, 28 Aug 2019 11:41:01 +0700 Subject: [erlang-questions] Testing gen_statem timers In-Reply-To: References: Message-ID: Hi, > On the other hand, mocking also introduces a layer of "this passes the tests but in reality it's not being tested" correct? I'm not very familiar with mocking in tests. For me, you should not use Unit Testing as an evidence to guarantee your system working well in reality. To do that, you should doing Integration Testing so you will never met a thing called "Mock" so it can guarantee your system working well in reality. Unit testing is excellent for locking your rules, locking your logic flow so nobody can change your rules, logic carelessly. Cheers! Pada tanggal Sab, 17 Agu 2019 pukul 23.44 Micael Nussbaumer < micaelnussbaumer@REDACTED> menulis: > Hi, thank you all for your inputs. I ended up doing a trace as Raimo > suggested and it works fine > the test > > > I think I could also have implemented `format_status` for the gen_statem > and extract the timers tuple from it? Not sure. Regarding having an API for > it I think it could be useful since that implementation detail is opaque. > > Torben, thank you sharing your lib - it looks like it can be quite handy > but in this particular case it's for a library as well and I would rather > not use a dependency, and since the timer options in the gen_statem work > great by default I would like to keep using those instead of incurring > another message to set the timer & executing a callback. I can definitively > understand the appeal of having it instead be mockable though. > > For the timeouts when I wrote the module that uses these timers I added > the option of setting their value on start, so that indeed I would be able > to test the behaviour easily in terms of ms and for that part it works > great. It was just this detail that was bugging me. > On the other hand, mocking also introduces a layer of "this passes the > tests but in reality it's not being tested" correct? I'm not very familiar > with mocking in tests. > > Roger, thank you so much for taking the time to extract that! So I ended > up doing the state inspection instead, I haven't used dbg yet but it looks > like it can be useful. What is the difference between using dbg instead of > the bare trace? > I guess now by looking at your example that indeed I could have done the > same approach by tracing the timer sets/cancels instead of tracing the call > functions and extracting the state, that is probably cleaner. > > Raimo, I replied to you by accident privately when using the list web gui > - I thought it was going to the "thread" as a reply to you. And yes, > perhaps on the sys:get_status it could include by default/on option also an > element for the timers? I did in fact try calling that at some point after > your first reply: > > {data,[{"Status",running}, > > {"Parent",<0.86.0>}, > > {"Logged Events",[]}, > > {"Postponed",[]}]}, > > Anyway, thank you all, great reading your replies, > > Micael > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fchschneider@REDACTED Wed Aug 28 08:45:47 2019 From: fchschneider@REDACTED (Frans Schneider) Date: Wed, 28 Aug 2019 08:45:47 +0200 Subject: [erlang-questions] phash2 portability Message-ID: <9106264e-2b1b-0c3f-bb10-b05db45712e5@gmail.com> Hi list, According to the docs, the erlang:phash2/2 will return the same result regardless of machine architecture and ERTS version. Does this imply that this is still true in case the implementation of a basic type, lets say a list or map (#{}), will change in the future? Can I assume that calculating a hash for a list will have the same result now and in the future? Thanks Frans From zkessin@REDACTED Wed Aug 28 15:36:49 2019 From: zkessin@REDACTED (Zachary Kessin) Date: Wed, 28 Aug 2019 09:36:49 -0400 Subject: [erlang-questions] Rebar3 Proper producing Junit style XML output Message-ID: Hi Erlang Crew! I am introducing PropER into my team here and we use Jenkins for our CI server and it would be really helpful if it could product XML in the format that JUnit does which is what Jenkins is expecting. Does anyone know if it can do this? I was not able to see anything in the docs page Zach Kessin +1 508 745 7940 https://youtu.be/Z3Yk7ipAAyk ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From t@REDACTED Wed Aug 28 15:42:32 2019 From: t@REDACTED (Tristan Sloughter) Date: Wed, 28 Aug 2019 07:42:32 -0600 Subject: [erlang-questions] Rebar3 Proper producing Junit style XML output In-Reply-To: References: Message-ID: <568ffe4d-89d8-41ea-a2e3-8931278c30c4@www.fastmail.com> If there isn't a proper specific tool for this you can use common test's cth_surefire hook that generates junit output by calling the tests from a CT suite http://erlang.org/doc/man/ct_property_test.html On Wed, Aug 28, 2019, at 07:37, Zachary Kessin wrote: > Hi Erlang Crew! > > I am introducing PropER into my team here and we use Jenkins for our CI server and it would be really helpful if it could product XML in the format that JUnit does which is what Jenkins is expecting. Does anyone know if it can do this? I was not able to see anything in the docs page > > Zach Kessin +1 508 745 7940 > https://youtu.be/Z3Yk7ipAAyk > > ? > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lukas@REDACTED Wed Aug 28 17:18:44 2019 From: lukas@REDACTED (Lukas Larsson) Date: Wed, 28 Aug 2019 17:18:44 +0200 Subject: [erlang-questions] phash2 portability In-Reply-To: <9106264e-2b1b-0c3f-bb10-b05db45712e5@gmail.com> References: <9106264e-2b1b-0c3f-bb10-b05db45712e5@gmail.com> Message-ID: On Wed, Aug 28, 2019 at 8:45 AM Frans Schneider wrote: > Hi list, > > According to the docs, the erlang:phash2/2 will return the same result > regardless of machine architecture and ERTS version. Does this imply > that this is still true in case the implementation of a basic type, lets > say a list or map (#{}), will change in the future? Can I assume that > calculating a hash for a list will have the same result now and in the > future? > Yes. The way hashing of maps works is that it hashes each k/v pair and then takes the xor of each of those hashes. Since a series of xor's can be applied in any order without changing the result, the hash value will always be the same. > > Thanks > > > Frans > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From publicityifl@REDACTED Wed Aug 28 17:21:18 2019 From: publicityifl@REDACTED (Jurriaan Hage) Date: Wed, 28 Aug 2019 08:21:18 -0700 Subject: [erlang-questions] First call for draft papers for TFPIE 2020 (Trends in Functional Programming in Education) Message-ID: Hello, Please, find below the final call for draft papers for TFPIE 2020. Please forward these to anyone you think may be interested. Apologies for any duplicates you may receive. best regards, Jurriaan Hage Chair of TFPIE 2020 ======================================================================== TFPIE 2020 Call for papers http://www.staff.science.uu.nl/~hage0101/tfpie2020/index.html February 12th 2020, Krakow, Poland (co-located with TFP 2020 and Lambda Days) TFPIE 2020 welcomes submissions describing techniques used in the classroom, tools used in and/or developed for the classroom and any creative use of functional programming (FP) to aid education in or outside Computer Science. Topics of interest include, but are not limited to: FP and beginning CS students FP and Computational Thinking FP and Artificial Intelligence FP in Robotics FP and Music Advanced FP for undergraduates FP in graduate education Engaging students in research using FP FP in Programming Languages FP in the high school curriculum FP as a stepping stone to other CS topics FP and Philosophy The pedagogy of teaching FP FP and e-learning: MOOCs, automated assessment etc. Best Lectures - more details below In addition to papers, we are requesting best lecture presentations. What's your best lecture topic in an FP related course? Do you have a fun way to present FP concepts to novices or perhaps an especially interesting presentation of a difficult topic? In either case, please consider sharing it. Best lecture topics will be selected for presentation based on a short abstract describing the lecture and its interest to TFPIE attendees. The length of the presentation should be comparable to that of a paper. On top of the lecture itself, the presentation can also provide commentary on the lecture. Submissions Potential presenters are invited to submit an extended abstract (4-6 pages) or a draft paper (up to 20 pages) in EPTCS style. The authors of accepted presentations will have their preprints and their slides made available on the workshop's website. Papers and abstracts can be submitted via easychair at the following link: https://easychair.org/conferences/?conf=tfpie2020 . After the workshop, presenters will be invited to submit (a revised version of) their article for review. The PC will select the best articles that will be published in the Electronic Proceedings in Theoretical Computer Science (EPTCS). Articles rejected for presentation and extended abstracts will not be formally reviewed by the PC. Dates Submission deadline: January 14th 2020, Anywhere on Earth. Notification: January 17th 2020 TFPIE Registration Deadline: January 20th 2020 Workshop: February 12th 2020 Submission for formal review: April 19th 2020, Anywhere on Earth. Notification of full article: June 6th 2020 Camera ready: July 1st 2020 Program Committee Olaf Chitil - University of Kent Youyou Cong - Tokyo Institute of Technology Marko van Eekelen - Open University of the Netherlands and Radboud University Nijmegen Jurriaan Hage (Chair) - Utrecht University Marco T. Morazan - Seton Hall University, USA Sharon Tuttle - Humboldt State University, USA Janis Voigtlaender - University of Duisburg-Essen Viktoria Zsok - Eotvos Lorand University Note: information on TFP is available at http://www.cse.chalmers.se/~rjmh/tfp/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From zkessin@REDACTED Wed Aug 28 19:01:43 2019 From: zkessin@REDACTED (Zachary Kessin) Date: Wed, 28 Aug 2019 13:01:43 -0400 Subject: [erlang-questions] Rebar3 Proper producing Junit style XML output In-Reply-To: <568ffe4d-89d8-41ea-a2e3-8931278c30c4@www.fastmail.com> References: <568ffe4d-89d8-41ea-a2e3-8931278c30c4@www.fastmail.com> Message-ID: Thanks Tristan, that should do the trick Zach Kessin zach@REDACTED +1 508 745 7940 https://youtu.be/Z3Yk7ipAAyk ? On Wed, Aug 28, 2019 at 9:43 AM Tristan Sloughter wrote: > If there isn't a proper specific tool for this you can use common test's > cth_surefire hook that generates junit output by calling the tests from a > CT suite http://erlang.org/doc/man/ct_property_test.html > > On Wed, Aug 28, 2019, at 07:37, Zachary Kessin wrote: > > Hi Erlang Crew! > > I am introducing PropER into my team here and we use Jenkins for our CI > server and it would be really helpful if it could product XML in the format > that JUnit does which is what Jenkins is expecting. Does anyone know if it > can do this? I was not able to see anything in the docs page > > Zach Kessin +1 508 745 7940 > https://youtu.be/Z3Yk7ipAAyk > > ? > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From silviu.cpp@REDACTED Wed Aug 28 23:30:36 2019 From: silviu.cpp@REDACTED (Caragea Silviu) Date: Thu, 29 Aug 2019 00:30:36 +0300 Subject: [erlang-questions] strange definition of enif_get_uint64 Message-ID: Hello, On a Mac OS 10.13.6 x64 in the osx headers the uint_64_t is defined as: #ifndef _UINT64_T #define _UINT64_T typedef unsigned long long uint64_t; #endif /* _UINT64_T */ But NIF function enif_get_uint64 is defined as # define enif_get_uint64 enif_get_ulong which accepts an unsigned long Any idea why is like this ? Silviu -------------- next part -------------- An HTML attachment was scrubbed... URL: From Scott.Finnie@REDACTED Thu Aug 29 08:59:21 2019 From: Scott.Finnie@REDACTED (Scott Finnie) Date: Thu, 29 Aug 2019 06:59:21 +0000 Subject: [erlang-questions] How best to resolve apparent inconsistency between re:run and string:slice Message-ID: Hello all I discovered an apparent inconsistency between re:run/2 and string:slice/2 last night. I'd appreciate any suggestions on the right way to solve. Best illustrated by this example: 1> S1="\rDogs". "\rDogs" 2> S2="\r\nDogs". "\r\nDogs" 3> {match, [{_, To1}]}=re:run(S1, "^\r"). {match,[{0,1}]} 4> {match, [{_, To2}]}=re:run(S2, "^\r\n"). {match,[{0,2}]} 5> string:slice(S1,To1). "Dogs" 6> string:slice(S2,To2). "ogs" I'd guess this is due to string:slice treating "\r\n" as a single lexeme, whereas re:run treats it as two characters. What I'm trying to achieve is consistent behaviour that (a) recognises any newline (CR, LF, CRLF, ...) at the start of the string and removes it. I also need a count of the contiguous newlines found. As an aside, the now-obsolete string:sub_string/2 does seem to work consistently: 7> string:sub_string(S1,To1+1). "Dogs" 8> string:sub_string(S2,To2+1). "Dogs" Thanks, Scott. ________________________________ -------------------- Hymans Robertson LLP is a limited liability partnership registered in England and Wales with registered number OC310282. A list of members of Hymans Robertson LLP is available for inspection at One London Wall, London, EC2Y 5EA, the firm's registered office. Hymans Robertson LLP is authorised and regulated by the Financial Conduct Authority and licensed by the Institute and Faculty of Actuaries for a range of investment business activities. This e-mail and any attachments are confidential. If it is not intended for you then please tell us and respect that confidentiality. E-mails and attachments can be corrupted or altered after sending: if you rely on advice or product transmitted by e-mail then you do so at your own risk. This footnote also confirms that this email message has been swept for the presence of computer viruses. Visit hymans.co.uk/information/privacy-notice/ for details of how we use your personal information. -------------------- -------------- next part -------------- An HTML attachment was scrubbed... URL: From mikpelinux@REDACTED Thu Aug 29 09:40:22 2019 From: mikpelinux@REDACTED (Mikael Pettersson) Date: Thu, 29 Aug 2019 09:40:22 +0200 Subject: [erlang-questions] strange definition of enif_get_uint64 In-Reply-To: References: Message-ID: On Wed, Aug 28, 2019 at 11:30 PM Caragea Silviu wrote: > > Hello, > > On a Mac OS 10.13.6 x64 in the osx headers the uint_64_t is defined as: > > #ifndef _UINT64_T > #define _UINT64_T > typedef unsigned long long uint64_t; > #endif /* _UINT64_T */ > > But NIF function enif_get_uint64 is defined as > > # define enif_get_uint64 enif_get_ulong > > which accepts an unsigned long > > Any idea why is like this ? The definitiion of enif_get_uint64 is conditional on the size of C's long type; the case you quoted only applies when long _is_ 64 bits. (Typically long is 32 bits on 32-bit machines and 64 bits on 64-bit machines, with long long always being 64 bits, but some OS:es (Windows) insists on keeping long 32 bits even in 64-bit environments. This is just one of many small details we have to handle when writing C code that's supposed to work on many CPUs and OS:es.) From silviu.cpp@REDACTED Thu Aug 29 10:34:51 2019 From: silviu.cpp@REDACTED (Caragea Silviu) Date: Thu, 29 Aug 2019 11:34:51 +0300 Subject: [erlang-questions] strange definition of enif_get_uint64 In-Reply-To: References: Message-ID: But why not just using they definitions from stdint.h on platforms where this one exists ? Idea is that the way is right now creates lot of conversions warnings if using NIF in mix with other libs that respects the standard. And I need to put lot of casts to avoid them Silviu On Thu, Aug 29, 2019 at 10:40 AM Mikael Pettersson wrote: > On Wed, Aug 28, 2019 at 11:30 PM Caragea Silviu > wrote: > > > > Hello, > > > > On a Mac OS 10.13.6 x64 in the osx headers the uint_64_t is defined as: > > > > #ifndef _UINT64_T > > #define _UINT64_T > > typedef unsigned long long uint64_t; > > #endif /* _UINT64_T */ > > > > But NIF function enif_get_uint64 is defined as > > > > # define enif_get_uint64 enif_get_ulong > > > > which accepts an unsigned long > > > > Any idea why is like this ? > > The definitiion of enif_get_uint64 is conditional on the size of C's > long type; the case you quoted only applies when long _is_ 64 bits. > > (Typically long is 32 bits on 32-bit machines and 64 bits on 64-bit > machines, with long long always being 64 bits, but some OS:es > (Windows) insists on keeping long 32 bits even in 64-bit environments. > This is just one of many small details we have to handle when writing > C code that's supposed to work on many CPUs and OS:es.) > -------------- next part -------------- An HTML attachment was scrubbed... URL: From 2QdxY4RzWzUUiLuE@REDACTED Thu Aug 29 10:36:32 2019 From: 2QdxY4RzWzUUiLuE@REDACTED (Dan Sommers) Date: Thu, 29 Aug 2019 04:36:32 -0400 Subject: [erlang-questions] How best to resolve apparent inconsistency between re:run and string:slice In-Reply-To: <20190829070248.87B965C01B@hades.cslab.ericsson.net> References: <20190829070248.87B965C01B@hades.cslab.ericsson.net> Message-ID: On 8/29/19 2:59 AM, Scott Finnie wrote: > What I?m trying to achieve is consistent behaviour that (a) recognises > any newline (CR, LF, CRLF, ?) at the start of the string and removes > it. I also need a count of the contiguous newlines found. Regular expressions seem needlessly complicated for this task. I'd use something more direct. Assuming that you want to count CRs and LFs separately, and not recognize CRLF as a single new line: %% return a {String, Counter} tuple where the leading CRs and LFs %% have stripped from String and counted in Counter count_and_strip_leading_crs_and_lfs(String) -> count_and_strip_leading_crs_and_lfs(String, 0). count_and_strip_leading_crs_and_lfs([$\r | String], Counter) -> count_and_strip_leading_crs_and_lfs(String, Counter + 1); count_and_strip_leading_crs_and_lfs([$\n | String], Counter) -> count_and_strip_leading_crs_and_lfs(String, Counter + 1); count_and_strip_leading_crs_and_lfs(String, Counter) -> {String, Counter}. To count CRLFs as a single new line, add this to the beginning of count_and_strip_leading_crs_and_lfs/2: count_and_strip_leading_crs_and_lfs([$\r, $\n | String], Counter) -> count_and_strip_leading_crs_and_lfs(String, Counter + 1); HTH, Dan From max.lapshin@REDACTED Thu Aug 29 12:49:37 2019 From: max.lapshin@REDACTED (Max Lapshin) Date: Thu, 29 Aug 2019 13:49:37 +0300 Subject: [erlang-questions] Thanks for new erlang logger: it is almost perfect Message-ID: Hi. We were using lager for about 7 years and have rewritten it to our own subsystem called "events" (not opensourced and possible will not be). Why? Because logging has changed. In the ancient times of old sysadmins with beards that are boasting big uptime, logging was a synonym of appending lines to text file and extracting data from these lines with a perl script. Things like webalyzer or radius were an ancient ancestors of modern ELK/Clickhouse stack. Nowadays logging is changing and it seems that it has completely splitted into 2 different data streams. One data stream is consumed by business analytics. It is collecting events from happy path. Request started, request finished, upstream request made, etc. Here we need to log structured key-value objects that are collected from all servers of the project and linked together according to some metadata like "request-id" or "user-id" Another data stream is about exceptions. They need to be collected and sent directly to developer tool like Sentry (on-premises and free. It is excellent) or Airbrake (good old service). So we have changed from lager:info("HTTP request handled") to events:http_request([{ip,IP},{user_id,UserId},....]). "events" is our own module with small preprocessor that takes all calls like events:http_request on compile time and checks if they are defined in config file. Thus we can simulate some kind of static typing and give our customers documentation on all methods without grep. In config file it is possible to declare sinks like: notify broken_video_stream { only media=mystream; sink http://logger-server/logs.php; } Then appeared new logger and I see that it has: 1) metadata. It is very, very important. Metadata is more important than text of message. In our events we have following approach: events:http_request([{ip,IP},{user_id,UserId},{method,Method}]). and {http_request, ["HTTP request from ip ",ip, {user_id, [" user_id ",user_id],""}, " to ",method]}. Yes, it is lager conditional formatting and it is really good. Metadata for robots, text line for sysadmins debugging this software. 2) remote proxy. Very cool. It happened to be designed exactly 1-1 as we have designed in Flussonic, so it seems that we have done it right =) 3) lack of central process. error_logger and lager were a big problem for us because they had single bottleneck that was working even for debug messages. Very often lager_event became a reason of crash for flussonic, so we have removed it and now it is ok. However, I see that we have a bit more complicated mechanism of log buffering and handler overload. https://gist.github.com/maxlapshin/ea632f04f79188aaba46d3a92406f8f6#file-events_router-erl-L94 Before sending message to log handler, we check if it is overloaded, then check its configuration and only after this we send message to log sink. Overloading is checked by each sink itself: it sends message to itself: https://gist.github.com/maxlapshin/7873727e3f93519cf4bb14287264fd3d#file-events_sink-erl-L15 All this is very important, because logging must not kill system due to slow disk or network. I want to thank again for new system, I will think how to combine our private logging subsystem with standard infrastructure. If our system is of some interest, I can open it code and explain our design ideas. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Scott.Finnie@REDACTED Thu Aug 29 13:09:31 2019 From: Scott.Finnie@REDACTED (Scott Finnie) Date: Thu, 29 Aug 2019 11:09:31 +0000 Subject: [erlang-questions] How best to resolve apparent inconsistency between re:run and string:slice In-Reply-To: References: <20190829070248.87B965C01B@hades.cslab.ericsson.net> Message-ID: Thanks for the response Dan, >> What I'm trying to achieve is consistent behaviour that (a) recognises > any newline (CR, LF, CRLF, ...) at the start of the string and removes > it. I also need a count of the contiguous newlines found. >Regular expressions seem needlessly complicated for this task. In the example I gave, I'd agree. In reality there are quite a few lexemes that constitute a newline. The full regex is "^(?>\r\n|\n|\x0b|\f|\r|\x85)". Adding a function clause for each of those would mean quite a lot of code duplication. There is perhaps a halfway house though, where it matches on a regex but doesn't rely on the {From, To} match result in taking the new string slice. It still leaves unresolved the seeming inconsistency between re:run and string:slice - though I appreciate you focused on suggesting an approach to my 1st order problem, not the 2nd order symptom. Thanks again for your suggestion. -S. _______________________________________________ erlang-questions mailing list erlang-questions@REDACTED http://erlang.org/mailman/listinfo/erlang-questions ________________________________ -------------------- Hymans Robertson LLP is a limited liability partnership registered in England and Wales with registered number OC310282. A list of members of Hymans Robertson LLP is available for inspection at One London Wall, London, EC2Y 5EA, the firm's registered office. Hymans Robertson LLP is authorised and regulated by the Financial Conduct Authority and licensed by the Institute and Faculty of Actuaries for a range of investment business activities. This e-mail and any attachments are confidential. If it is not intended for you then please tell us and respect that confidentiality. E-mails and attachments can be corrupted or altered after sending: if you rely on advice or product transmitted by e-mail then you do so at your own risk. This footnote also confirms that this email message has been swept for the presence of computer viruses. Visit hymans.co.uk/information/privacy-notice/ for details of how we use your personal information. -------------------- From dave.wolf@REDACTED Thu Aug 29 18:39:12 2019 From: dave.wolf@REDACTED (Wolf, Dave) Date: Thu, 29 Aug 2019 16:39:12 +0000 Subject: [erlang-questions] MIB compiler errors for common MIBS In-Reply-To: References: Message-ID: Hi all, I am working on an SNMP application that polls SNMP devices and currently it works fine if I use OIDs, but I'd like to be able to load the MIB file for the device and poll using the name associated with the OID. The issue I am running into is that for most of my MIB files I downloaded from the manufacturer sites, the MIB compiler in Erlang encounters errors during the compile to .bin format. I am wondering if I need to compile it in a certain directory, but I am not sure why it is failing. Here are beginning lines of the output from an example (full errors attached in output.txt) of this command: "erlc UPS-MIB.mib". I have tried this on Windows and Linux hosts with the same results. UPS-MIB.mib: 38: Macro 'TEXTUAL-CONVENTION' not imported. UPS-MIB.mib: 45: Macro 'TEXTUAL-CONVENTION' not imported. UPS-MIB.mib: 18: OBJECT IDENTIFIER [upsMIB] defined in terms of undefined parent object. Parent: ''mib-2''.(Sub-indexes: [33].) UPS-MIB.mib: 52: OBJECT IDENTIFIER [upsObjects] defined in terms of undefined parent object. Parent: 'upsMIB'.(Sub-indexes: [1].) UPS-MIB.mib: 62: OBJECT IDENTIFIER [upsIdent] defined in terms of undefined parent object. Parent: 'upsObjects'.(Sub-indexes: [1].) UPS-MIB.mib: 64: OBJECT IDENTIFIER [upsIdentManufacturer] defined in terms of undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [1].) UPS-MIB.mib: 72: OBJECT IDENTIFIER [upsIdentModel] defined in terms of undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [2].) <> I've attached the MIB file in case someone wants to give it a shot and tell me the errors of my ways. I have loaded this exact MIB file into a MIB browser and it works just fine, I can browse the device without any issues. Is there another way I can compile this MIB file? Is it in a common format that other tools might be able to compile? If anyone has any suggestions or needs further infomation, please let me know. Thanks! Dave Wolf. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: UPS-MIB.mib Type: application/octet-stream Size: 67040 bytes Desc: UPS-MIB.mib URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: output.txt URL: From per@REDACTED Thu Aug 29 18:58:37 2019 From: per@REDACTED (Per Hedeland) Date: Thu, 29 Aug 2019 18:58:37 +0200 Subject: [erlang-questions] strange definition of enif_get_uint64 In-Reply-To: References: Message-ID: On 2019-08-29 10:34, Caragea Silviu wrote: > But why not just using they definitions from stdint.h on platforms where this one exists ? +1. I guess the reason is historical, from back when stdint.h (part of the C99 standard AFAIK) wasn't widely avaible or at least known, and instead these 'configure'-based "private" typedefs were used. But these days I really wonder if anyone is running Erlang on a platform that doesn't have stdint.h. > Idea is that the way is right now creates lot of conversions warnings if using NIF in mix with other libs that respects the standard. And I need to put lot of casts to avoid them Another problem is with cross compilation - in a native build, 'configure' can reliably determine the correct typedefs by running sizeof()-tests, but for a cross build, the user has to tell it, and had better get it right. In fact just the other week I came across someone having ended up with ErlNifUInt64 being an "unsigned long" in a cross build for a 32-bit system, i.e. only 32 bits (perhaps whoever was to blame had done a manual sizeof() test on the 64-bit build system). Using stdint.h "just works" in my experience, both for portability (no need for 'configure' for *that* at least) and for cross builds - it would really be an improvement. --Per > Silviu > > On Thu, Aug 29, 2019 at 10:40 AM Mikael Pettersson > wrote: > > On Wed, Aug 28, 2019 at 11:30 PM Caragea Silviu > wrote: > > > > Hello, > > > > On a Mac OS 10.13.6 x64 in the osx headers the uint_64_t is defined as: > > > > #ifndef _UINT64_T > > #define _UINT64_T > > typedef unsigned long long uint64_t; > > #endif /* _UINT64_T */ > > > > But NIF function enif_get_uint64 is defined as > > > > # define enif_get_uint64 enif_get_ulong > > > > which accepts an unsigned long > > > > Any idea why is like this ? > > The definitiion of enif_get_uint64 is conditional on the size of C's > long type; the case you quoted only applies when long _is_ 64 bits. > > (Typically long is 32 bits on 32-bit machines and 64 bits on 64-bit > machines, with long long always being 64 bits, but some OS:es > (Windows) insists on keeping long 32 bits even in 64-bit environments. > This is just one of many small details we have to handle when writing > C code that's supposed to work on many CPUs and OS:es.) > > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > From mikpelinux@REDACTED Thu Aug 29 20:08:32 2019 From: mikpelinux@REDACTED (Mikael Pettersson) Date: Thu, 29 Aug 2019 20:08:32 +0200 Subject: [erlang-questions] strange definition of enif_get_uint64 In-Reply-To: References: Message-ID: On Thu, Aug 29, 2019 at 10:35 AM Caragea Silviu wrote: > > But why not just using they definitions from stdint.h on platforms where this one exists ? Presumably legacy from the times when stdint.h wasn't widely available. Also, in most cases it works fine to use equivalent (wrt size and sign) but syntactically different types. > Idea is that the way is right now creates lot of conversions warnings if using NIF in mix with other libs that respects the standard. And I need to put lot of casts to avoid them Presumably pointers or printf/scanf formats are involved, as e.g. a 64-bit long and a likewise 64-bit long long are fully assignment-compatible, but pointers to them are not, and C compilers like to warn when seeing "the wrong" printf/scanf format letter for an argument even if they happen to match on the current target. Yes, preference should be to use and as far as possible, but OTP's development cycles are limited. From dszoboszlay@REDACTED Thu Aug 29 21:41:16 2019 From: dszoboszlay@REDACTED (=?UTF-8?Q?D=C3=A1niel_Szoboszlay?=) Date: Thu, 29 Aug 2019 21:41:16 +0200 Subject: [erlang-questions] MIB compiler errors for common MIBS In-Reply-To: References: Message-ID: Hi, My memories about the OTP MIB compiler are not very fresh, but back in the days I used it a lot I noticed that it's much more picky than other MIB-handling tools. Errors like the ones you encountered had to be fixed manually in most MIBs we got from equipment vendors. For example the TEXTUAL-CONVENTION macro is defined in SNMPv2-TC, and I guess most other tools simply auto-import all these definitions from the standard MIBs. When working with the OTP MIB compiler, you have to explicitly import it. mib-2 is similarly defined in SNMPv2-SMI, and you have to explicitly import it from there. An other common issue was object identifiers defined in reverse order (parent comes after child in the MIB file). You have to simply reverse the order of the definitions to please the compiler. Hope it helps, Daniel On Thu, 29 Aug 2019 at 18:46, Wolf, Dave wrote: > Hi all, > > > > I am working on an SNMP application that polls SNMP devices and currently > it works fine if I use OIDs, but I?d like to be able to load the MIB file > for the device and poll using the name associated with the OID. The issue > I am running into is that for most of my MIB files I downloaded from the > manufacturer sites, the MIB compiler in Erlang encounters errors during the > compile to .bin format. I am wondering if I need to compile it in a > certain directory, but I am not sure why it is failing. Here are beginning > lines of the output from an example (full errors attached in output.txt) of > this command: ?erlc UPS-MIB.mib?. I have tried this on Windows and Linux > hosts with the same results. > > > > UPS-MIB.mib: 38: Macro 'TEXTUAL-CONVENTION' not imported. > > UPS-MIB.mib: 45: Macro 'TEXTUAL-CONVENTION' not imported. > > UPS-MIB.mib: 18: OBJECT IDENTIFIER [upsMIB] defined in terms of undefined > parent object. Parent: ''mib-2''.(Sub-indexes: [33].) > > UPS-MIB.mib: 52: OBJECT IDENTIFIER [upsObjects] defined in terms of > undefined parent object. Parent: 'upsMIB'.(Sub-indexes: [1].) > > UPS-MIB.mib: 62: OBJECT IDENTIFIER [upsIdent] defined in terms of > undefined parent object. Parent: 'upsObjects'.(Sub-indexes: [1].) > > UPS-MIB.mib: 64: OBJECT IDENTIFIER [upsIdentManufacturer] defined in terms > of undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [1].) > > UPS-MIB.mib: 72: OBJECT IDENTIFIER [upsIdentModel] defined in terms of > undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [2].) > > <> > > > > I?ve attached the MIB file in case someone wants to give it a shot and > tell me the errors of my ways. I have loaded this exact MIB file into a > MIB browser and it works just fine, I can browse the device without any > issues. Is there another way I can compile this MIB file? Is it in a > common format that other tools might be able to compile? > > > > If anyone has any suggestions or needs further infomation, please let me > know. > > > > Thanks! > > Dave Wolf. > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dave.wolf@REDACTED Fri Aug 30 16:04:24 2019 From: dave.wolf@REDACTED (Wolf, Dave) Date: Fri, 30 Aug 2019 14:04:24 +0000 Subject: [erlang-questions] MIB compiler errors for common MIBS In-Reply-To: References: Message-ID: Hi Daniel, Thanks, this helps a lot; however, I am now met with another set of errors that I can?t seem to figure out as well, from another MIB file we are using from RackPower for their line of PDUs. I?m met with several of these errors below (full list is in attached output.txt file). OBJECT-TYPE is imported by SNMPv2-SMI, so that shouldn?t be an issue. What puzzles me is the ?not-accessible? possibility. I?ve looked at the objects in my first file I posted from yesterday and these don?t look different and that file compiles after the assistance I received yesterday. I gotta be missing something. I appreciate the responses I have received, this is all rather new and I am slowly learning. Any assistance anyone can provide would be greatly appreciated! Thanks, Dave. C:\Program Files\erl10.1\lib\snmp-5.2.12\mibs>erlc RACKPOWER-MIB.mib RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayModel' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayFirmware' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayName' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayLocation' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayMacAddress' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayIpAddressIpv4' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewaySubnetIpv4' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayGatewayIpv4' RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' for 'pduIndex' RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' for 'pduModel' RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' for 'pduID' RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' for 'pduName' <> From: erlang-questions-bounces@REDACTED On Behalf Of D?niel Szoboszlay Sent: Thursday, August 29, 2019 3:41 PM To: erlang-questions@REDACTED Subject: Re: [erlang-questions] MIB compiler errors for common MIBS Hi, My memories about the OTP MIB compiler are not very fresh, but back in the days I used it a lot I noticed that it's much more picky than other MIB-handling tools. Errors like the ones you encountered had to be fixed manually in most MIBs we got from equipment vendors. For example the TEXTUAL-CONVENTION macro is defined in SNMPv2-TC, and I guess most other tools simply auto-import all these definitions from the standard MIBs. When working with the OTP MIB compiler, you have to explicitly import it. mib-2 is similarly defined in SNMPv2-SMI, and you have to explicitly import it from there. An other common issue was object identifiers defined in reverse order (parent comes after child in the MIB file). You have to simply reverse the order of the definitions to please the compiler. Hope it helps, Daniel On Thu, 29 Aug 2019 at 18:46, Wolf, Dave > wrote: Hi all, I am working on an SNMP application that polls SNMP devices and currently it works fine if I use OIDs, but I?d like to be able to load the MIB file for the device and poll using the name associated with the OID. The issue I am running into is that for most of my MIB files I downloaded from the manufacturer sites, the MIB compiler in Erlang encounters errors during the compile to .bin format. I am wondering if I need to compile it in a certain directory, but I am not sure why it is failing. Here are beginning lines of the output from an example (full errors attached in output.txt) of this command: ?erlc UPS-MIB.mib?. I have tried this on Windows and Linux hosts with the same results. UPS-MIB.mib: 38: Macro 'TEXTUAL-CONVENTION' not imported. UPS-MIB.mib: 45: Macro 'TEXTUAL-CONVENTION' not imported. UPS-MIB.mib: 18: OBJECT IDENTIFIER [upsMIB] defined in terms of undefined parent object. Parent: ''mib-2''.(Sub-indexes: [33].) UPS-MIB.mib: 52: OBJECT IDENTIFIER [upsObjects] defined in terms of undefined parent object. Parent: 'upsMIB'.(Sub-indexes: [1].) UPS-MIB.mib: 62: OBJECT IDENTIFIER [upsIdent] defined in terms of undefined parent object. Parent: 'upsObjects'.(Sub-indexes: [1].) UPS-MIB.mib: 64: OBJECT IDENTIFIER [upsIdentManufacturer] defined in terms of undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [1].) UPS-MIB.mib: 72: OBJECT IDENTIFIER [upsIdentModel] defined in terms of undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [2].) <> I?ve attached the MIB file in case someone wants to give it a shot and tell me the errors of my ways. I have loaded this exact MIB file into a MIB browser and it works just fine, I can browse the device without any issues. Is there another way I can compile this MIB file? Is it in a common format that other tools might be able to compile? If anyone has any suggestions or needs further infomation, please let me know. Thanks! Dave Wolf. _______________________________________________ erlang-questions mailing list erlang-questions@REDACTED http://erlang.org/mailman/listinfo/erlang-questions -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: RACKPOWER-MIB.mib Type: application/octet-stream Size: 56418 bytes Desc: RACKPOWER-MIB.mib URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: output.txt URL: From dave.wolf@REDACTED Fri Aug 30 16:57:23 2019 From: dave.wolf@REDACTED (Wolf, Dave) Date: Fri, 30 Aug 2019 14:57:23 +0000 Subject: [erlang-questions] MIB compiler errors for common MIBS In-Reply-To: References: Message-ID: After further review, I have fixed all of the errors, except the following (they were as Daniel described, object identifiers defined in reverse order): C:\Program Files\erl10.1\lib\snmp-5.2.12\mibs>erlc RACKPOWER-MIB.mib RACKPOWER-MIB.mib: 1654: Corrupt table definition. RACKPOWER-MIB.mib: Table 'pduTable' must have at least one accessible column. compilation_failed If anyone could help with this last one, I would be very grateful! Thanks, Dave. From: erlang-questions-bounces@REDACTED On Behalf Of [ext] Wolf, Dave Sent: Friday, August 30, 2019 10:04 AM To: D?niel Szoboszlay ; erlang-questions@REDACTED Subject: Re: [erlang-questions] MIB compiler errors for common MIBS Hi Daniel, Thanks, this helps a lot; however, I am now met with another set of errors that I can?t seem to figure out as well, from another MIB file we are using from RackPower for their line of PDUs. I?m met with several of these errors below (full list is in attached output.txt file). OBJECT-TYPE is imported by SNMPv2-SMI, so that shouldn?t be an issue. What puzzles me is the ?not-accessible? possibility. I?ve looked at the objects in my first file I posted from yesterday and these don?t look different and that file compiles after the assistance I received yesterday. I gotta be missing something. I appreciate the responses I have received, this is all rather new and I am slowly learning. Any assistance anyone can provide would be greatly appreciated! Thanks, Dave. C:\Program Files\erl10.1\lib\snmp-5.2.12\mibs>erlc RACKPOWER-MIB.mib RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayModel' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayFirmware' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayName' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayLocation' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayMacAddress' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayIpAddressIpv4' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewaySubnetIpv4' RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' for 'ipgatewayGatewayIpv4' RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' for 'pduIndex' RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' for 'pduModel' RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' for 'pduID' RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' for 'pduName' <> From: erlang-questions-bounces@REDACTED > On Behalf Of D?niel Szoboszlay Sent: Thursday, August 29, 2019 3:41 PM To: erlang-questions@REDACTED Subject: Re: [erlang-questions] MIB compiler errors for common MIBS Hi, My memories about the OTP MIB compiler are not very fresh, but back in the days I used it a lot I noticed that it's much more picky than other MIB-handling tools. Errors like the ones you encountered had to be fixed manually in most MIBs we got from equipment vendors. For example the TEXTUAL-CONVENTION macro is defined in SNMPv2-TC, and I guess most other tools simply auto-import all these definitions from the standard MIBs. When working with the OTP MIB compiler, you have to explicitly import it. mib-2 is similarly defined in SNMPv2-SMI, and you have to explicitly import it from there. An other common issue was object identifiers defined in reverse order (parent comes after child in the MIB file). You have to simply reverse the order of the definitions to please the compiler. Hope it helps, Daniel On Thu, 29 Aug 2019 at 18:46, Wolf, Dave > wrote: Hi all, I am working on an SNMP application that polls SNMP devices and currently it works fine if I use OIDs, but I?d like to be able to load the MIB file for the device and poll using the name associated with the OID. The issue I am running into is that for most of my MIB files I downloaded from the manufacturer sites, the MIB compiler in Erlang encounters errors during the compile to .bin format. I am wondering if I need to compile it in a certain directory, but I am not sure why it is failing. Here are beginning lines of the output from an example (full errors attached in output.txt) of this command: ?erlc UPS-MIB.mib?. I have tried this on Windows and Linux hosts with the same results. UPS-MIB.mib: 38: Macro 'TEXTUAL-CONVENTION' not imported. UPS-MIB.mib: 45: Macro 'TEXTUAL-CONVENTION' not imported. UPS-MIB.mib: 18: OBJECT IDENTIFIER [upsMIB] defined in terms of undefined parent object. Parent: ''mib-2''.(Sub-indexes: [33].) UPS-MIB.mib: 52: OBJECT IDENTIFIER [upsObjects] defined in terms of undefined parent object. Parent: 'upsMIB'.(Sub-indexes: [1].) UPS-MIB.mib: 62: OBJECT IDENTIFIER [upsIdent] defined in terms of undefined parent object. Parent: 'upsObjects'.(Sub-indexes: [1].) UPS-MIB.mib: 64: OBJECT IDENTIFIER [upsIdentManufacturer] defined in terms of undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [1].) UPS-MIB.mib: 72: OBJECT IDENTIFIER [upsIdentModel] defined in terms of undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [2].) <> I?ve attached the MIB file in case someone wants to give it a shot and tell me the errors of my ways. I have loaded this exact MIB file into a MIB browser and it works just fine, I can browse the device without any issues. Is there another way I can compile this MIB file? Is it in a common format that other tools might be able to compile? If anyone has any suggestions or needs further infomation, please let me know. Thanks! Dave Wolf. _______________________________________________ erlang-questions mailing list erlang-questions@REDACTED http://erlang.org/mailman/listinfo/erlang-questions -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: RACKPOWER-MIB.mib Type: application/octet-stream Size: 56432 bytes Desc: RACKPOWER-MIB.mib URL: From dszoboszlay@REDACTED Fri Aug 30 20:36:25 2019 From: dszoboszlay@REDACTED (=?UTF-8?Q?D=C3=A1niel_Szoboszlay?=) Date: Fri, 30 Aug 2019 20:36:25 +0200 Subject: [erlang-questions] MIB compiler errors for common MIBS In-Reply-To: References: Message-ID: Try reordering the definitions related to the pduTable like this: pduTable (the table definition) pduEntry (the row definition) definitions of all the columns in the table in the order they appear in the pduEntry sequence (so pduIndex, pduModel, pduID, ...) Make sure no other object definitions are left between the above (so e.g. define circuitTable and its row and columns after fully defining everything related to pduTable). Keeping definitions of all objects related to a table together in one block is one more thing the MIB compiler is picky about. Also, if table X uses a column from table Y as an index (e.g. simlar to circuitTable using pduIndex as an index) than X should be defined after Y. I hope you won't run into any more issues, because I'm running out of tips & tricks. :) I remember we once encountered a MIB with a table where the row's OID was not the { tableOID 1} but { tableOID 2 } or something. This definition was impossible to compile with OTP, and we either had to change the MIB or patch OTP, I don't remember which one. Fingers crossed for you not to encounter any weirdness like this! Cheers, Daniel On Fri, 30 Aug 2019 at 16:57, Wolf, Dave wrote: > After further review, I have fixed all of the errors, except the following > (they were as Daniel described, object identifiers defined in reverse > order): > > > > C:\Program Files\erl10.1\lib\snmp-5.2.12\mibs>erlc RACKPOWER-MIB.mib > > RACKPOWER-MIB.mib: 1654: Corrupt table definition. > > RACKPOWER-MIB.mib: Table 'pduTable' must have at least one accessible > column. > > compilation_failed > > > > If anyone could help with this last one, I would be very grateful! > > > > Thanks, > > Dave. > > > > *From:* erlang-questions-bounces@REDACTED < > erlang-questions-bounces@REDACTED> *On Behalf Of *[ext] Wolf, Dave > *Sent:* Friday, August 30, 2019 10:04 AM > *To:* D?niel Szoboszlay ; > erlang-questions@REDACTED > *Subject:* Re: [erlang-questions] MIB compiler errors for common MIBS > > > > Hi Daniel, > > > > Thanks, this helps a lot; however, I am now met with another set of errors > that I can?t seem to figure out as well, from another MIB file we are using > from RackPower for their line of PDUs. I?m met with several of these > errors below (full list is in attached output.txt file). OBJECT-TYPE is > imported by SNMPv2-SMI, so that shouldn?t be an issue. What puzzles me is > the ?not-accessible? possibility. I?ve looked at the objects in my first > file I posted from yesterday and these don?t look different and that file > compiles after the assistance I received yesterday. I gotta be missing > something. I appreciate the responses I have received, this is all rather > new and I am slowly learning. Any assistance anyone can provide would be > greatly appreciated! > > > > Thanks, > > Dave. > > > > C:\Program Files\erl10.1\lib\snmp-5.2.12\mibs>erlc RACKPOWER-MIB.mib > > RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' > for 'ipgatewayModel' > > RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' > for 'ipgatewayFirmware' > > RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' > for 'ipgatewayName' > > RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' > for 'ipgatewayLocation' > > RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' > for 'ipgatewayMacAddress' > > RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' > for 'ipgatewayIpAddressIpv4' > > RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' > for 'ipgatewaySubnetIpv4' > > RACKPOWER-MIB.mib: 100: OBJECT-TYPE definition missing or 'not-accessible' > for 'ipgatewayGatewayIpv4' > > RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' > for 'pduIndex' > > RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' > for 'pduModel' > > RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' > for 'pduID' > > RACKPOWER-MIB.mib: 114: OBJECT-TYPE definition missing or 'not-accessible' > for 'pduName' > > <> > > > > > > *From:* erlang-questions-bounces@REDACTED < > erlang-questions-bounces@REDACTED> *On Behalf Of *D?niel Szoboszlay > *Sent:* Thursday, August 29, 2019 3:41 PM > *To:* erlang-questions@REDACTED > *Subject:* Re: [erlang-questions] MIB compiler errors for common MIBS > > > > Hi, > > > > My memories about the OTP MIB compiler are not very fresh, but back in the > days I used it a lot I noticed that it's much more picky than other > MIB-handling tools. Errors like the ones you encountered had to be fixed > manually in most MIBs we got from equipment vendors. For example the > TEXTUAL-CONVENTION macro is defined in SNMPv2-TC, and I guess most other > tools simply auto-import all these definitions from the standard MIBs. When > working with the OTP MIB compiler, you have to explicitly import it. mib-2 > is similarly defined in SNMPv2-SMI, and you have to explicitly import it > from there. > > > > An other common issue was object identifiers defined in reverse order > (parent comes after child in the MIB file). You have to simply reverse the > order of the definitions to please the compiler. > > > > Hope it helps, > > Daniel > > > > On Thu, 29 Aug 2019 at 18:46, Wolf, Dave wrote: > > Hi all, > > > > I am working on an SNMP application that polls SNMP devices and currently > it works fine if I use OIDs, but I?d like to be able to load the MIB file > for the device and poll using the name associated with the OID. The issue > I am running into is that for most of my MIB files I downloaded from the > manufacturer sites, the MIB compiler in Erlang encounters errors during the > compile to .bin format. I am wondering if I need to compile it in a > certain directory, but I am not sure why it is failing. Here are beginning > lines of the output from an example (full errors attached in output.txt) of > this command: ?erlc UPS-MIB.mib?. I have tried this on Windows and Linux > hosts with the same results. > > > > UPS-MIB.mib: 38: Macro 'TEXTUAL-CONVENTION' not imported. > > UPS-MIB.mib: 45: Macro 'TEXTUAL-CONVENTION' not imported. > > UPS-MIB.mib: 18: OBJECT IDENTIFIER [upsMIB] defined in terms of undefined > parent object. Parent: ''mib-2''.(Sub-indexes: [33].) > > UPS-MIB.mib: 52: OBJECT IDENTIFIER [upsObjects] defined in terms of > undefined parent object. Parent: 'upsMIB'.(Sub-indexes: [1].) > > UPS-MIB.mib: 62: OBJECT IDENTIFIER [upsIdent] defined in terms of > undefined parent object. Parent: 'upsObjects'.(Sub-indexes: [1].) > > UPS-MIB.mib: 64: OBJECT IDENTIFIER [upsIdentManufacturer] defined in terms > of undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [1].) > > UPS-MIB.mib: 72: OBJECT IDENTIFIER [upsIdentModel] defined in terms of > undefined parent object. Parent: 'upsIdent'.(Sub-indexes: [2].) > > <> > > > > I?ve attached the MIB file in case someone wants to give it a shot and > tell me the errors of my ways. I have loaded this exact MIB file into a > MIB browser and it works just fine, I can browse the device without any > issues. Is there another way I can compile this MIB file? Is it in a > common format that other tools might be able to compile? > > > > If anyone has any suggestions or needs further infomation, please let me > know. > > > > Thanks! > > Dave Wolf. > > _______________________________________________ > erlang-questions mailing list > erlang-questions@REDACTED > http://erlang.org/mailman/listinfo/erlang-questions > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: