If you use datavtype, then you do not have to deal with
views explicitly. It is just a style.

I myself tend to use datavtype when memory allocation is involved and
record (plus at-view) in an embedded setting where not memory allocation
is involved.

As for efficiency, there is no difference; internally, the same 
representation is
used.

On Wednesday, March 8, 2017 at 8:11:06 AM UTC-5, August Alm wrote:
>
> In my original formulation of CSVState (not using a datavtype but a 
> concrete vtypedef) I can add
>
> infix +=
> macdef(x, i) = ,(x) := ,(x) + ,(i)
>
> and then write
>
> st.2->tableRow += 1  
>
> The best I can do with a datavtype is something like
>
> st.tableRow_inc(1)
>
> They are comparable to my eyes, as far as readability of code is concerned.
>
> How does my vtypedef-version compare with your datavtype-version in terms 
> of efficiency? Is there a clear optimization reason to choose one over the 
> other?
>
> Den onsdag 8 mars 2017 kl. 10:18:45 UTC+1 skrev August Alm:
>>
>> I see. Yes, being able to write
>>
>> st.tableRow(2)
>>
>> instead of
>>
>> st.2->tableRow := 2
>>
>> would make the code a little cleaner, I guess, What would really reduce 
>> syntacic noise in my code though would be a slick way of writing what 
>> currently I have as
>>
>> st.2->tableRow := st.2->tableRow + 1
>>
>> Continuing your suggestion, I can write something like
>>
>> extern fun {}
>> CSVState_update_tableRow (
>>   st: !CSVState,
>>   up: int -> int
>> ) : void 
>>
>> implement {}
>> CSVState_update_tableRow(st, up) = 
>> let val @CSVState(s) = st
>> in s.tableRow := up(s.tableRow); fold@(st)
>> end
>>
>> fun {}
>> plus(n: int): (int -> int) = lam(i) => n + i
>>
>> overload .tableRow with CSVState_update_tableRow
>>
>> After this I can write
>>
>> st.tableRow(plus(1))
>>
>> Is there a way to use overloading that would let me write that instead as
>>
>> st.tableRow(+1)  ?
>>
>> I tried "overload + with plus" but get the error "operator fixity cannot 
>> be resolved" when used.
>>
>>
>> Den onsdag 8 mars 2017 kl. 02:03:33 UTC+1 skrev gmhwxi:
>>>
>>> I was referring to some kind of code of the following style:
>>>
>>> typedef
>>> CSVState_rec =
>>> @{
>>>   tableRow = int,
>>>   tableCol = int,
>>>   textRow = int,
>>>   textCol = int
>>> }
>>>
>>> datavtype
>>> CSVState = CSVState of CSVState_rec
>>>
>>> extern
>>> fun{}
>>> CSVState_get_tableRow(!CSVState): int
>>> extern
>>> fun{}
>>> CSVState_set_tableRow(!CSVState, int): void
>>> overload .tableRow with CSVState_get_tableRow
>>> overload .tableRow with CSVState_set_tableRow
>>>
>>> implement
>>> {}
>>> CSVState_get_tableRow
>>>   (state) = let
>>> //
>>> val+CSVState(x0) = state in x0.tableRow
>>> //
>>> end // end of [CSVState_get_tableRow]
>>> implement
>>> {}
>>> CSVState_set_tableRow
>>>   (state, i0) = let
>>> //
>>> val+@CSVState(x0) = state in x0.tableRow := i0; fold@(state)
>>> //
>>> end // end of [CSVState_set_tableRow]
>>> typedef
>>> CSVState_rec =
>>> @{
>>>   tableRow = int,
>>>   tableCol = int,
>>>   textRow = int,
>>>   textCol = int
>>> }
>>>
>>> datavtype
>>> CSVState = CSVState of CSVState_rec
>>>
>>> extern
>>> fun{}
>>> CSVState_get_tableRow(!CSVState): int
>>> extern
>>> fun{}
>>> CSVState_set_tableRow(!CSVState, int): void
>>> overload .tableRow with CSVState_get_tableRow
>>> overload .tableRow with CSVState_set_tableRow
>>>
>>> implement
>>> {}
>>> CSVState_get_tableRow
>>>   (state) = let
>>> //
>>> val+CSVState(x0) = state in x0.tableRow
>>> //
>>> end // end of [CSVState_get_tableRow]
>>> implement
>>> {}
>>> CSVState_set_tableRow
>>>   (state, i0) = let
>>> //
>>> val+@CSVState(x0) = state in x0.tableRow := i0; fold@(state)
>>> //
>>> end // end of [CSVState_set_tableRow]
>>>
>>> On Tuesday, March 7, 2017 at 4:52:58 PM UTC-5, August Alm wrote:
>>>>
>>>> I'm glad too! I wrote my first "Hello World" program (in Haskell) less 
>>>> than four months ago, before that I was completely illiterate about 
>>>> programming--writing a linear, lazy CSV-parser in ATS has definitely been 
>>>> my most challenging venture so far. I mean this in a good way. ATS is 
>>>> quickly becoming my favorite language. It is daunting at times, sure, but 
>>>> its unique combination of low-level abilities and functional abstractions 
>>>> makes me feel like the Star Trek idiom "To boldly go where no one has gone 
>>>> before", heh. The ATS sky is so vast I've almost forgot about monads. And 
>>>> YES!, I do suggest trying ATS to every programmer I meet. 
>>>>
>>>> Tangential to the topic of monads: Do you know if someone has thought 
>>>> about the relations between ATS and "enriched effect calculus" (as 
>>>> described in http://homepages.inf.ed.ac.uk/als/Research/Sources/eec.pdf) 
>>>> or "linear state monads" (as mentioned in 
>>>> https://arxiv.org/pdf/1403.1477.pdf)? There is a clear analogy. 
>>>> Implementing a concept such as a linear state monad in ATS would be nice, 
>>>> I 
>>>> think. Monadic programming on an Arduino, anyone? =) It would certainly be 
>>>> a unique selling point.
>>>>
>>>> I do not understand what you're aiming at with your suggestion to maje 
>>>> CSVState a datavtype or absvtype. Could you elaborate? I have seen 
>>>> abstract 
>>>> types used as a way to make otherwise allowed operation illegal (there is 
>>>> an example in your book, I think, of how to construct a record type where 
>>>> some fields are mutable and some are not), but not for the sake of 
>>>> overloading symbols.
>>>>
>>>> I will rewrite the code so that DELIM and QNLIN are passed as 
>>>> templates. I also intend to add some further functionality, like functions 
>>>> for filtering out errors, for printing and for collecting the output in 
>>>> tabular form with rows and columns rather than as a single row. When I'm 
>>>> satisfied I will make an npm-package out of it.
>>>>
>>>> Best wishes,
>>>> August
>>>>
>>>> Den tisdag 7 mars 2017 kl. 02:21:00 UTC+1 skrev gmhwxi:
>>>>>
>>>>> Really glad that you got it to work!
>>>>>
>>>>> I suggest that you make a npm-package for the parser and then
>>>>> publish the package. In this way, other ats-lang users can benefit
>>>>> from your work easily.
>>>>>
>>>>> You could try to introduce some abstract types into your code. For
>>>>> instance, I would suggest that you make CSVstate a datavtype (linear 
>>>>> datatype)
>>>>> (a datatype is often referred to as being semi-abstract). Then you can
>>>>> introduce overloaded symbols for functions processing CSVstate, making 
>>>>> your code
>>>>> more accessible.
>>>>>
>>>>> Also, the following interface:
>>>>>
>>>>> extern fun 
>>>>> lex_csv(QNLIN: bool, DELIM: char, cs: llstring): CSVEntries 
>>>>>
>>>>> can and probably should be changed into
>>>>>
>>>>> extern
>>>>> fun{}
>>>>> lex_csv(cs: listing): CSVEntries
>>>>>
>>>>> The parameters QNLIN and DELIM can be passed via templates:
>>>>>
>>>>> extern
>>>>> fun{} lex_csv$QNLIN(): char
>>>>> extern
>>>>> fun{} lex_csv$DELIM(): char
>>>>>
>>>>> implement{} lex_csv$QNLIN() = false
>>>>> implement{} lex_csv$DELIM() = ',' // default value
>>>>>
>>>>> Writing function templates (instead of functions) enables you to move
>>>>> your code around very conveniently. You can even move template code
>>>>> into the body of another function.
>>>>>
>>>>> That's all for now. Hope you will like ATS and tell/teach it to your 
>>>>> friends.
>>>>>
>>>>> Cheers!
>>>>>
>>>>> On Monday, March 6, 2017 at 4:06:11 PM UTC-5, August Alm wrote:
>>>>>>
>>>>>> The code now seems to work as inteded!
>>>>>>
>>>>>> https://github.com/August-Alm/ats_csv_lexer
>>>>>>
>>>>>> Thank you for all the help. I still don't fully grokk why the 
>>>>>> function needs to consume each of its arguments--will have to meditate 
>>>>>> more 
>>>>>> on that--but at least I know how to write code like this from now on. 
>>>>>>
>>>>>> Den måndag 6 mars 2017 kl. 17:43:36 UTC+1 skrev gmhwxi:
>>>>>>>
>>>>>>> Yes, CSVstate needs to be changed as well.
>>>>>>>
>>>>>>> However, your code needs very little change. This is like a
>>>>>>> a 5 minute job to me. I would be happy to give it a try if you say 
>>>>>>> so.
>>>>>>> But I thought that you might want to get the thrill of fixing the 
>>>>>>> code :)
>>>>>>>
>>>>>>> On Monday, March 6, 2017 at 11:30:27 AM UTC-5, August Alm wrote:
>>>>>>>>
>>>>>>>> Hrrm, I had:
>>>>>>>>
>>>>>>>> fun
>>>>>>>> parse_entry
>>>>>>>> ( st: !CSVState >> _
>>>>>>>> , at: (int, int)
>>>>>>>> , acc: !$SBF.stringbuf
>>>>>>>> , cs: llstring
>>>>>>>> ) : stream_vt(CSVEntry)
>>>>>>>>
>>>>>>>> I gather I have to change not just [!$SBF.stringbuf] but also 
>>>>>>>> [!CSVState >> _], right? What about if I did
>>>>>>>>
>>>>>>>> fun
>>>>>>>> parse_entry_con
>>>>>>>> ( st: !CSVState >> _
>>>>>>>> , at: (int, int)
>>>>>>>> , acc: !$SBF.stringbuf
>>>>>>>> , cs: llstring
>>>>>>>> ) : stream_vt_con(CSVEntry)
>>>>>>>>
>>>>>>>> and then put 
>>>>>>>>
>>>>>>>> parse_entry(...) = 
>>>>>>>> $ldelay
>>>>>>>> ( parse_entry_con(...)
>>>>>>>> , ( free(st)
>>>>>>>>   ; free(acc)
>>>>>>>>   ; free(cs)
>>>>>>>>   )
>>>>>>>> )
>>>>>>>>
>>>>>>>> --would that work? Would it be idiomatic and efficient?
>>>>>>>>
>>>>>>>> Thanks, again,
>>>>>>>> August
>>>>>>>>
>>>>>>>> Den måndag 6 mars 2017 kl. 14:30:05 UTC+1 skrev gmhwxi:
>>>>>>>>>
>>>>>>>>> I forgot to tell you something essential in using stream_vt.
>>>>>>>>> The following interface for 'test' cannot work:
>>>>>>>>>
>>>>>>>>> fun test (acc: !$SBF.stringbuf, cs: llstring): stream_vt(DT) =
>>>>>>>>>
>>>>>>>>> What you need is
>>>>>>>>>
>>>>>>>>> fun test (acc: $SBF.stringbuf, cs: llstring): stream_vt(DT) =
>>>>>>>>>
>>>>>>>>> The 'acc' stringbuf needs to be consumed by 'test'. The 
>>>>>>>>> implementation
>>>>>>>>> of 'test' looks like this:
>>>>>>>>>
>>>>>>>>> $ldelay
>>>>>>>>> (
>>>>>>>>> <code for stream construction>
>>>>>>>>> ,
>>>>>>>>> (freeing(acc); freeing(cs)) // this part is executed when the 
>>>>>>>>> stream is freed
>>>>>>>>> )
>>>>>>>>>
>>>>>>>>> On Mon, Mar 6, 2017 at 8:19 AM, August Alm <augu...@gmail.com> 
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> The points you mention are part of the reason I chose to wrote 
>>>>>>>>>> the csv lexer the way I did. It follows one of the fastests Haskell 
>>>>>>>>>> csv 
>>>>>>>>>> parsers, and I was curious to see how using linear types could 
>>>>>>>>>> optimize 
>>>>>>>>>> performance.
>>>>>>>>>>
>>>>>>>>>> Regarding your suggestion on how to make better use of $ldelay in 
>>>>>>>>>> my code: I'm stuck on a compiler error that I can't make sense of. 
>>>>>>>>>> The 
>>>>>>>>>> following pseudo-minimal example throws the same kind of errors:
>>>>>>>>>>          
>>>>>>>>>>          #include "share/atspre_define.hats"
>>>>>>>>>>          #include "share/atspre_staload.hats"
>>>>>>>>>>          staload UN = "prelude/SATS/unsafe.sats"
>>>>>>>>>>          staload SBF = "libats/SATS/stringbuf.sats"
>>>>>>>>>>          staload _(*SBF*) = "libats/DATS/stringbuf.dats"
>>>>>>>>>>          
>>>>>>>>>>          datatype DT = D_T of @{ alpha = char }
>>>>>>>>>>          vtypedef llstring = stream_vt(char)
>>>>>>>>>>          
>>>>>>>>>>          fun
>>>>>>>>>>          test (acc: !$SBF.stringbuf, cs: llstring): stream_vt(DT) 
>>>>>>>>>> =
>>>>>>>>>>          $ldelay
>>>>>>>>>>          ( case !cs of
>>>>>>>>>>            | ~stream_vt_nil() =>
>>>>>>>>>>              if $SBF.stringbuf_get_size(acc) = i2sz(0) then 
>>>>>>>>>> stream_vt_nil()
>>>>>>>>>>              else stream_vt_cons(D_T(@{alpha = 'a'}), 
>>>>>>>>>> stream_vt_make_nil())
>>>>>>>>>>            | ~stream_vt_cons(c, cs1) =>
>>>>>>>>>>              let val crec = D_T(@{alpha = c})
>>>>>>>>>>              in stream_vt_cons(crec, test(acc, cs1))
>>>>>>>>>>              end
>>>>>>>>>>          , ~cs
>>>>>>>>>>          )
>>>>>>>>>>
>>>>>>>>>> The compiler can not infer the type I want (which is 
>>>>>>>>>> [stream_vt_con(DT)] for the [stream_vt_nil()] following the first 
>>>>>>>>>> [then] in 
>>>>>>>>>> the function body. The error message says
>>>>>>>>>>
>>>>>>>>>> the dynamic expression cannot be assigned the type [S2EVar(5492)].
>>>>>>>>>> [...] mismatch of sorts in unification:
>>>>>>>>>> The sort of variable is: S2RTbas(S2RTBASimp(1; t@ype))
>>>>>>>>>> The sort of solution is: S2RTbas(S2RTBASimp(2; viewtype))
>>>>>>>>>> [...] mismatch of static terms (tyleq):
>>>>>>>>>> The actual term is: S2Eapp(S2Ecst(stream_vt_con); S2EVar(5495))
>>>>>>>>>> The needed term is: S2EVar(5492)
>>>>>>>>>>
>>>>>>>>>> (There are further errors of the same form.) Is the culprit that 
>>>>>>>>>> [stream_vt] of a nonlinear datatype requires some special care? The 
>>>>>>>>>> version 
>>>>>>>>>> with [stream_vt_make_nil()] instead of explicit [$ldelay] works so 
>>>>>>>>>> the 
>>>>>>>>>> error ought to be subtle.
>>>>>>>>>>
>>>>>>>>>> Best wishes,
>>>>>>>>>> August
>>>>>>>>>>
>>>>>>>>>> Den söndag 5 mars 2017 kl. 23:58:35 UTC+1 skrev gmhwxi:
>>>>>>>>>>>
>>>>>>>>>>> Yes, you definitely got it :)
>>>>>>>>>>>
>>>>>>>>>>> Stream_vt is very memory-frugal.
>>>>>>>>>>>
>>>>>>>>>>> Haskell relies on deforestation (complex complier optimization)
>>>>>>>>>>> to reduce memory usage of lazy evaluation. In ATS, deforestation 
>>>>>>>>>>> is
>>>>>>>>>>> not supported. Instead, the programmer needs to recycle memory 
>>>>>>>>>>> explicitly.
>>>>>>>>>>>
>>>>>>>>>>> Compared to Haskell, corresponding code using stream_vt in ATS 
>>>>>>>>>>> can be
>>>>>>>>>>> much more efficient both time-wise and memory-wise.
>>>>>>>>>>>
>>>>>>>>>>> For instance, the following example (for computing Mersenne 
>>>>>>>>>>> primes) can
>>>>>>>>>>> run for days without run-time GC:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> https://github.com/githwxi/ATS-Postiats/blob/master/doc/EXAMPLE/RosettaCode/Lucas-Lehmer_test2.dats
>>>>>>>>>>>
>>>>>>>>>>> It convincingly attests to the power of linear streams.
>>>>>>>>>>>
>>>>>>>>>>> Cheers!
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Sun, Mar 5, 2017 at 5:34 PM, August Alm <augu...@gmail.com> 
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Thanks for the tip! I think I understand. I treated $ldelay 
>>>>>>>>>>>> much as a data constructor, so that all streams are equally lazy, 
>>>>>>>>>>>> whereas 
>>>>>>>>>>>> there are in fact many ways to sequence into thunks. Let me give 
>>>>>>>>>>>> an example 
>>>>>>>>>>>> to anchor the discussion. Both the following implementations of a 
>>>>>>>>>>>> map-template for linear streams typecheck:
>>>>>>>>>>>>
>>>>>>>>>>>>          fun {a, b: t0ype}
>>>>>>>>>>>>          map_make_cons 
>>>>>>>>>>>>          ( xs: stream_vt(a)
>>>>>>>>>>>>          , f: a -> b
>>>>>>>>>>>>          ) : stream_vt(b) =
>>>>>>>>>>>>          case !xs of
>>>>>>>>>>>>          | ~stream_vt_nil() => stream_vt_make_nil()
>>>>>>>>>>>>          | ~stream_vt_cons(x, xs1) =>
>>>>>>>>>>>>            stream_vt_make_cons(f(x), map_make_cons(xs1, f))
>>>>>>>>>>>>          
>>>>>>>>>>>>          fun {a, b: t0ype}
>>>>>>>>>>>>          map_ldelay
>>>>>>>>>>>>          ( xs: stream_vt(a)
>>>>>>>>>>>>          , f: a -> b
>>>>>>>>>>>>          ) : stream_vt(b) =
>>>>>>>>>>>>          $ldelay
>>>>>>>>>>>>          ( case !xs of
>>>>>>>>>>>>            | ~stream_vt_nil() => stream_vt_nil()
>>>>>>>>>>>>            | ~stream_vt_cons(x, xs1) =>
>>>>>>>>>>>>              stream_vt_cons(f(x), map_ldelay(xs1, f))
>>>>>>>>>>>>          , ~xs
>>>>>>>>>>>>          )
>>>>>>>>>>>>
>>>>>>>>>>>> The second is maximally lazy. The first, [map_make_cons] is 
>>>>>>>>>>>> less lazy because checking the case-conditions is not delayed. My 
>>>>>>>>>>>> code was 
>>>>>>>>>>>> like the first example, only much more was going on inside the 
>>>>>>>>>>>> case 
>>>>>>>>>>>> expressions. Is that a correct assessment?
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Den söndag 5 mars 2017 kl. 04:07:42 UTC+1 skrev gmhwxi:
>>>>>>>>>>>>>
>>>>>>>>>>>>> BTW, it seems you don't need to do much to fix the issue.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Basically, you just do
>>>>>>>>>>>>>
>>>>>>>>>>>>> 1) Put the body of parse_entry into $ldelay(...)
>>>>>>>>>>>>> 2) Change stream_vt_make_cons into stream_vt_cons
>>>>>>>>>>>>>
>>>>>>>>>>>>> There may be a few other things but they should all be
>>>>>>>>>>>>> very minor.
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Saturday, March 4, 2017 at 9:47:07 PM UTC-5, gmhwxi wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I took a glance at your code.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I noticed a very common mistake involving the use of
>>>>>>>>>>>>>> stream (or stream_vt). Basically, the way stream is used
>>>>>>>>>>>>>> in your code is like the way list is used. This causes the
>>>>>>>>>>>>>> stack issue you encountered.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Say that you have a function that returns a stream. In nearly
>>>>>>>>>>>>>> all cases, the correct way to implement such a function should
>>>>>>>>>>>>>> use the following style:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> fun foo(...): stream_vt(...) = $ldelay
>>>>>>>>>>>>>> (
>>>>>>>>>>>>>> ...
>>>>>>>>>>>>>> )
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The idea is that 'foo' should return in O(1) time. The body 
>>>>>>>>>>>>>> of $ldelay
>>>>>>>>>>>>>> is only evaluated with the first element of the returned 
>>>>>>>>>>>>>> stream is neede.
>>>>>>>>>>>>>> Sometimes, this is call full laziness. Without full laziness, 
>>>>>>>>>>>>>> a stream may
>>>>>>>>>>>>>> behave like a list, defeating the very purpose of using a 
>>>>>>>>>>>>>> stream.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On Saturday, March 4, 2017 at 7:27:03 PM UTC-5, August Alm 
>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I've spent  few hours trying to figure out how to make 
>>>>>>>>>>>>>>> proper use of npm and gave up--for now. If the project turns 
>>>>>>>>>>>>>>> into something 
>>>>>>>>>>>>>>> more serious (i.e., useful to others) then I will have another 
>>>>>>>>>>>>>>> go at it. 
>>>>>>>>>>>>>>> For now my naive attempts at making effective use of linear 
>>>>>>>>>>>>>>> streams can be 
>>>>>>>>>>>>>>> witnessed at GitHub: 
>>>>>>>>>>>>>>> https://github.com/August-Alm/ats_csv_lexer Any and all 
>>>>>>>>>>>>>>> comments on how to improve are appreciated.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Best wishes, August.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 23:57:54 UTC+1 skrev gmhwxi:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> One possibility is to build a npm package and then publish 
>>>>>>>>>>>>>>>> it.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> If you go to https://www.npmjs.com/ and seach for 
>>>>>>>>>>>>>>>> 'atscntrb'. You can find
>>>>>>>>>>>>>>>> plenty packages. You may need to install npm first.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> If you do build a npm package, I suggest that you choose a 
>>>>>>>>>>>>>>>> name space for
>>>>>>>>>>>>>>>> yourself. E.g., atscntrb-a?a-..., where ? is the first 
>>>>>>>>>>>>>>>> letter of your middle name.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> On Fri, Mar 3, 2017 at 5:48 PM, August Alm <
>>>>>>>>>>>>>>>> augu...@gmail.com> wrote:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> How would I best share larger code portions? I have no 
>>>>>>>>>>>>>>>>> concerns about my making my mistakes public, heh.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> I believe everything is lazy as-is (all data is 
>>>>>>>>>>>>>>>>> [stream_vt("sometype")]). And I've tried to write 
>>>>>>>>>>>>>>>>> tail-recursive functional 
>>>>>>>>>>>>>>>>> code. The algorithm is based on two mutually recursing 
>>>>>>>>>>>>>>>>> functions, "fun ... 
>>>>>>>>>>>>>>>>> and ..", similar to how you did things in your csv-parser 
>>>>>>>>>>>>>>>>> (thanks for 
>>>>>>>>>>>>>>>>> pointing out that piece of code). However, I cannot set them 
>>>>>>>>>>>>>>>>> up with "fn* 
>>>>>>>>>>>>>>>>> .. and .." to enforce a local jump because they call each 
>>>>>>>>>>>>>>>>> other in a too 
>>>>>>>>>>>>>>>>> intertwined way. Might that be it?
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 23:32:15 UTC+1 skrev gmhwxi:
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> You are welcome!
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Since I have not seen your code, I could only guess :)
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Usually, what you described can be fixed by using 
>>>>>>>>>>>>>>>>>> tail-recursion, or
>>>>>>>>>>>>>>>>>> by using lazy-evaluation. The former approach is 
>>>>>>>>>>>>>>>>>> straightforward. You
>>>>>>>>>>>>>>>>>> just need to identify the function or functions that 
>>>>>>>>>>>>>>>>>> cause the deep stack
>>>>>>>>>>>>>>>>>> usage. Then try to rewrite using tail-recursion.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> On Fri, Mar 3, 2017 at 5:25 PM, August Alm <
>>>>>>>>>>>>>>>>>> augu...@gmail.com> wrote:
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>>>>>>> I had indeed made a logical error that caused any stream 
>>>>>>>>>>>>>>>>>>> with "carriage return" followed by "newline" to recurse 
>>>>>>>>>>>>>>>>>>> indefinitely. Thank 
>>>>>>>>>>>>>>>>>>> you for your patience and pedagogical instincts, Professor! 
>>>>>>>>>>>>>>>>>>> There is still 
>>>>>>>>>>>>>>>>>>> some issue though, one that I believe is more subtle. I 
>>>>>>>>>>>>>>>>>>> fixed the logical 
>>>>>>>>>>>>>>>>>>> error and my algorithm now handles all the test cases you 
>>>>>>>>>>>>>>>>>>> suggested. 
>>>>>>>>>>>>>>>>>>> However, when fed an actual CSV-file with a thousand rows 
>>>>>>>>>>>>>>>>>>> and about 300 
>>>>>>>>>>>>>>>>>>> columns it still segfaults--unless I manually increase the 
>>>>>>>>>>>>>>>>>>> stack space on 
>>>>>>>>>>>>>>>>>>> my computer! I don't know exactly where the critical limit 
>>>>>>>>>>>>>>>>>>> is, but 
>>>>>>>>>>>>>>>>>>> increasing it from 8192 kbytes to 65536 certainly did the 
>>>>>>>>>>>>>>>>>>> trick. The whole 
>>>>>>>>>>>>>>>>>>> file parsed without problem, and rather quickly at that. It 
>>>>>>>>>>>>>>>>>>> seems my 
>>>>>>>>>>>>>>>>>>> algorithm makes too much use of stack allocation and that I 
>>>>>>>>>>>>>>>>>>> may have to 
>>>>>>>>>>>>>>>>>>> rethink some of my (would-be) optimization choices.
>>>>>>>>>>>>>>>>>>> Best wishes,
>>>>>>>>>>>>>>>>>>> August
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 15:22:00 UTC+1 skrev gmhwxi:
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Now you may do the following tests:
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Try:
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> val ins = streamize_string_char("a;b") // should work
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Try:
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> val ins = streamize_string_char("a;b\n") // may not work
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Try:
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> val ins = streamize_string_char("a;b\015\012") // 
>>>>>>>>>>>>>>>>>>>> should cause crash
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> On Thursday, March 2, 2017 at 9:21:21 PM UTC-5, gmhwxi 
>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> When tried, I saw the following 5 chars (ascii) in 
>>>>>>>>>>>>>>>>>>>>> small.csv:
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> 97
>>>>>>>>>>>>>>>>>>>>> 59
>>>>>>>>>>>>>>>>>>>>> 98
>>>>>>>>>>>>>>>>>>>>> 13
>>>>>>>>>>>>>>>>>>>>> 10
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> My testing code:
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> #include"share/atspre_staload.hats"
>>>>>>>>>>>>>>>>>>>>> #include"share/HATS/atspre_staload_libats_ML.hats"
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> implement main0 () = {
>>>>>>>>>>>>>>>>>>>>>   val inp = fileref_open_exn("small.csv", file_mode_r)
>>>>>>>>>>>>>>>>>>>>>   val ins = streamize_fileref_char(inp)
>>>>>>>>>>>>>>>>>>>>>   val ins = stream2list_vt(ins)
>>>>>>>>>>>>>>>>>>>>>   val ins = g0ofg1(list_vt2t(ins))97
>>>>>>>>>>>>>>>>>>>>>   val ( ) = println! ("length(ins) = ", length(ins))
>>>>>>>>>>>>>>>>>>>>>   val ( ) = (ins).foreach()(lam c => 
>>>>>>>>>>>>>>>>>>>>> println!(char2int0(c)))
>>>>>>>>>>>>>>>>>>>>> (*
>>>>>>>>>>>>>>>>>>>>>   val lexed = lex_csv(true, ';', ins)
>>>>>>>>>>>>>>>>>>>>> *)
>>>>>>>>>>>>>>>>>>>>>   val () = fileref_close(inp)
>>>>>>>>>>>>>>>>>>>>> (*
>>>>>>>>>>>>>>>>>>>>>   val h = (lexed.head())
>>>>>>>>>>>>>>>>>>>>>   val- CSV_Field(r) = h
>>>>>>>>>>>>>>>>>>>>>   val a = r.csvFieldContent
>>>>>>>>>>>>>>>>>>>>>   val () = println!(a)
>>>>>>>>>>>>>>>>>>>>> *)
>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> On Thu, Mar 2, 2017 at 9:13 PM, August Alm <...> 
>>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> Just "a;b", or? (Attached.)
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 03:03:08 UTC+1 skrev 
>>>>>>>>>>>>>>>>>>>>>> gmhwxi:
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> I suspect that the file you used contains other 
>>>>>>>>>>>>>>>>>>>>>>> characters.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> What is in "small.csv"?
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> On Thu, Mar 2, 2017 at 8:52 PM, August Alm <...> 
>>>>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> The file compiles (I've tried a few compiler 
>>>>>>>>>>>>>>>>>>>>>>>> options) and "gdb run" yields
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>     Program received signal SIGSEGV, Segmentation 
>>>>>>>>>>>>>>>>>>>>>>>> fault.
>>>>>>>>>>>>>>>>>>>>>>>>     0x00007ffff783eea5 in _int_malloc 
>>>>>>>>>>>>>>>>>>>>>>>> (av=0x7ffff7b6a620 <main_arena>, bytes=16) at 
>>>>>>>>>>>>>>>>>>>>>>>> malloc.c:3790
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> The frames 0-3 involve allocation functions that 
>>>>>>>>>>>>>>>>>>>>>>>> are not particular to my file. Frame 4 says:
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>     #4  __patsfun_28__28__14 (arg0=<optimized out>, 
>>>>>>>>>>>>>>>>>>>>>>>> env1=0x605540, env0=10 '\n') at csv_lexer_dats.c:9023
>>>>>>>>>>>>>>>>>>>>>>>>     9023    ATSINSmove_con1_new(tmpret63__14, 
>>>>>>>>>>>>>>>>>>>>>>>> postiats_tysum_7) ;
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> My not-so-educated guess is that this refers to 
>>>>>>>>>>>>>>>>>>>>>>>> making a cons-cell of a stream.
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> But: How can my function do just fine when manually 
>>>>>>>>>>>>>>>>>>>>>>>> fed 
>>>>>>>>>>>>>>>>>>>>>>>>  
>>>>>>>>>>>>>>>>>>>>>>>>     cons('a', cons( ';', sing('b'))): 
>>>>>>>>>>>>>>>>>>>>>>>> stream_vt(char), 
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> but segfault when I use [streamize_fileref_char] to 
>>>>>>>>>>>>>>>>>>>>>>>> construct the very same stream from the string "a;b" 
>>>>>>>>>>>>>>>>>>>>>>>> in a file? Where is 
>>>>>>>>>>>>>>>>>>>>>>>> the room for an infinite recursion in that?
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> Thank you,
>>>>>>>>>>>>>>>>>>>>>>>> August
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> Den torsdag 2 mars 2017 kl. 23:04:35 UTC+1 skrev 
>>>>>>>>>>>>>>>>>>>>>>>> August Alm:
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> I'm in over my head and tried writing a CSV-parser 
>>>>>>>>>>>>>>>>>>>>>>>>> using linear lazy streams. My code thus far is 600 
>>>>>>>>>>>>>>>>>>>>>>>>> lines and almost to my 
>>>>>>>>>>>>>>>>>>>>>>>>> own surprise I get it to compile! However, there is 
>>>>>>>>>>>>>>>>>>>>>>>>> something fishy because 
>>>>>>>>>>>>>>>>>>>>>>>>> I get a segfault when applying my program to an 
>>>>>>>>>>>>>>>>>>>>>>>>> actual CSV-file. I've been 
>>>>>>>>>>>>>>>>>>>>>>>>> trying to debug using gdb but the fault eludes me. 
>>>>>>>>>>>>>>>>>>>>>>>>> Since I don't expect 
>>>>>>>>>>>>>>>>>>>>>>>>> anyone to mull through 600 lines of code, I am hoping 
>>>>>>>>>>>>>>>>>>>>>>>>> these code snippets 
>>>>>>>>>>>>>>>>>>>>>>>>> are enough for one of you guys to give me some advice.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> This code executes just fine:
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>         implement main0 () = {
>>>>>>>>>>>>>>>>>>>>>>>>>            
>>>>>>>>>>>>>>>>>>>>>>>>>            val test = stream_vt_make_cons(
>>>>>>>>>>>>>>>>>>>>>>>>>                             'a', 
>>>>>>>>>>>>>>>>>>>>>>>>> stream_vt_make_cons(
>>>>>>>>>>>>>>>>>>>>>>>>>                                     ';', 
>>>>>>>>>>>>>>>>>>>>>>>>> stream_vt_make_sing('b')))          (* the stream 
>>>>>>>>>>>>>>>>>>>>>>>>> ('a', ';', 'b') *)
>>>>>>>>>>>>>>>>>>>>>>>>>            val lexed = lex_csv(true, ';', test)
>>>>>>>>>>>>>>>>>>>>>>>>>            val h = (lexed.head())
>>>>>>>>>>>>>>>>>>>>>>>>>            val- CSV_Field(r) = h
>>>>>>>>>>>>>>>>>>>>>>>>>            val a = r.csvFieldContent
>>>>>>>>>>>>>>>>>>>>>>>>>            val () = println!(a)
>>>>>>>>>>>>>>>>>>>>>>>>>          
>>>>>>>>>>>>>>>>>>>>>>>>>          }
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> Here [lex_csv] is my 600-line alogrithm. It reads 
>>>>>>>>>>>>>>>>>>>>>>>>> a [stream_vt(char)] and gives back a 
>>>>>>>>>>>>>>>>>>>>>>>>> [stream_vt(CSVEntry)], where 
>>>>>>>>>>>>>>>>>>>>>>>>> [CSVEntry] is a record type, one of whose fields is 
>>>>>>>>>>>>>>>>>>>>>>>>> [CSVFieldContent]. When 
>>>>>>>>>>>>>>>>>>>>>>>>> executing the program I get "a" printed to the 
>>>>>>>>>>>>>>>>>>>>>>>>> console.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> This code results in a segfault:
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>         implement main0 () = {
>>>>>>>>>>>>>>>>>>>>>>>>>         
>>>>>>>>>>>>>>>>>>>>>>>>>            val inp = fileref_open_exn("small.csv", 
>>>>>>>>>>>>>>>>>>>>>>>>> file_mode_r)
>>>>>>>>>>>>>>>>>>>>>>>>>            val ins = streamize_fileref_char(inp)
>>>>>>>>>>>>>>>>>>>>>>>>>            val lexed = lex_csv(true, ';', ins)
>>>>>>>>>>>>>>>>>>>>>>>>>            val () = fileref_close(inp)
>>>>>>>>>>>>>>>>>>>>>>>>>            val h = (lexed.head())
>>>>>>>>>>>>>>>>>>>>>>>>>            val- CSV_Field(r) = h
>>>>>>>>>>>>>>>>>>>>>>>>>            val a = r.csvFieldContent
>>>>>>>>>>>>>>>>>>>>>>>>>            val () = println!(a)
>>>>>>>>>>>>>>>>>>>>>>>>>          
>>>>>>>>>>>>>>>>>>>>>>>>>          }
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> The file "small.csv" only contains the string 
>>>>>>>>>>>>>>>>>>>>>>>>> "a;b". Hence I would expect this code to give the 
>>>>>>>>>>>>>>>>>>>>>>>>> result as the previous 
>>>>>>>>>>>>>>>>>>>>>>>>> one! But, it doesn't just return something else, it 
>>>>>>>>>>>>>>>>>>>>>>>>> segfaults.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> gdb indicates there is a malloc problem having to 
>>>>>>>>>>>>>>>>>>>>>>>>> do with "GC_clear_stack_inner", in case that's 
>>>>>>>>>>>>>>>>>>>>>>>>> helpful. (I'm a 
>>>>>>>>>>>>>>>>>>>>>>>>> mathematician who recently left academia after 
>>>>>>>>>>>>>>>>>>>>>>>>> postdoc and decided to teach 
>>>>>>>>>>>>>>>>>>>>>>>>> myself programming to become more useful outside of 
>>>>>>>>>>>>>>>>>>>>>>>>> academia; hence I 
>>>>>>>>>>>>>>>>>>>>>>>>> understand type systems and the like--the mathy 
>>>>>>>>>>>>>>>>>>>>>>>>> stuff--a lot better than I 
>>>>>>>>>>>>>>>>>>>>>>>>> understand memory allocation and other stuff that 
>>>>>>>>>>>>>>>>>>>>>>>>> most programmers are 
>>>>>>>>>>>>>>>>>>>>>>>>> supposed to be confident with.)
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> What could be the problem here?
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> Best wishes,
>>>>>>>>>>>>>>>>>>>>>>>>> August
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> -- 
>>>>>>>>>>>>>>>>>>>>>>>> You received this message because you are 
>>>>>>>>>>>>>>>>>>>>>>>> subscribed to the Google Groups "ats-lang-users" group.
>>>>>>>>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving 
>>>>>>>>>>>>>>>>>>>>>>>> emails from it, send an email to 
>>>>>>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com.
>>>>>>>>>>>>>>>>>>>>>>>> To post to this group, send email to 
>>>>>>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com.
>>>>>>>>>>>>>>>>>>>>>>>> Visit this group at 
>>>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users.
>>>>>>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit 
>>>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/69535c5c-eac3-472c-bb39-062ad4708a72%40googlegroups.com
>>>>>>>>>>>>>>>>>>>>>>>>  
>>>>>>>>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/69535c5c-eac3-472c-bb39-062ad4708a72%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>>>>>>>>>>>>>>>> .
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> -- 
>>>>>>>>>>>>>>>>>>>>>> You received this message because you are subscribed 
>>>>>>>>>>>>>>>>>>>>>> to the Google Groups "ats-lang-users" group.
>>>>>>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving 
>>>>>>>>>>>>>>>>>>>>>> emails from it, send an email to 
>>>>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com.
>>>>>>>>>>>>>>>>>>>>>> To post to this group, send email to 
>>>>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com.
>>>>>>>>>>>>>>>>>>>>>> Visit this group at 
>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users.
>>>>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit 
>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/e608c7bb-42ce-457b-a606-9fe3525f801d%40googlegroups.com
>>>>>>>>>>>>>>>>>>>>>>  
>>>>>>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/e608c7bb-42ce-457b-a606-9fe3525f801d%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>>>>>>>>>>>>>> .
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> -- 
>>>>>>>>>>>>>>>>>>> You received this message because you are subscribed to 
>>>>>>>>>>>>>>>>>>> the Google Groups "ats-lang-users" group.
>>>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails 
>>>>>>>>>>>>>>>>>>> from it, send an email to 
>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com.
>>>>>>>>>>>>>>>>>>> To post to this group, send email to 
>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com.
>>>>>>>>>>>>>>>>>>> Visit this group at 
>>>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users.
>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit 
>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/34dfad01-9bd4-464f-9ccd-6dfae8207f4c%40googlegroups.com
>>>>>>>>>>>>>>>>>>>  
>>>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/34dfad01-9bd4-464f-9ccd-6dfae8207f4c%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>>>>>>>>>>> .
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> -- 
>>>>>>>>>>>>>>>>> You received this message because you are subscribed to 
>>>>>>>>>>>>>>>>> the Google Groups "ats-lang-users" group.
>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails 
>>>>>>>>>>>>>>>>> from it, send an email to 
>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com.
>>>>>>>>>>>>>>>>> To post to this group, send email to 
>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com.
>>>>>>>>>>>>>>>>> Visit this group at 
>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users.
>>>>>>>>>>>>>>>>> To view this discussion on the web visit 
>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/c2f9d2b7-61f5-4142-b8b2-930147ee589d%40googlegroups.com
>>>>>>>>>>>>>>>>>  
>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/c2f9d2b7-61f5-4142-b8b2-930147ee589d%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>>>>>>>>> .
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> -- 
>>>>>>>>>>>> You received this message because you are subscribed to the 
>>>>>>>>>>>> Google Groups "ats-lang-users" group.
>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from 
>>>>>>>>>>>> it, send an email to ats-lang-user...@googlegroups.com.
>>>>>>>>>>>> To post to this group, send email to 
>>>>>>>>>>>> ats-lan...@googlegroups.com.
>>>>>>>>>>>> Visit this group at 
>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users.
>>>>>>>>>>>> To view this discussion on the web visit 
>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/d78409e2-aff1-4b96-98f3-eb3a5d20ff95%40googlegroups.com
>>>>>>>>>>>>  
>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/d78409e2-aff1-4b96-98f3-eb3a5d20ff95%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>>>> .
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -- 
>>>>>>>>>> You received this message because you are subscribed to the 
>>>>>>>>>> Google Groups "ats-lang-users" group.
>>>>>>>>>> To unsubscribe from this group and stop receiving emails from it, 
>>>>>>>>>> send an email to ats-lang-user...@googlegroups.com.
>>>>>>>>>> To post to this group, send email to ats-lan...@googlegroups.com.
>>>>>>>>>> Visit this group at <a href="
>>>>>>>>>> https://groups.google.com/group/ats-lang-users"; rel="nofollow" 
>>>>>>>>>> target="_blank" onmousedown="this.href='
>>>>>>>>>> https://groups.google.com/group/ats-lang-users';return true;" 
>>>>>>>>>> onclick="this.href='
>>>>>>>>>> https://groups.google.com/group/ats-lang-users';return tr
>>>>>>>>>
>>>>>>>>>

-- 
You received this message because you are subscribed to the Google Groups 
"ats-lang-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to ats-lang-users+unsubscr...@googlegroups.com.
To post to this group, send email to ats-lang-users@googlegroups.com.
Visit this group at https://groups.google.com/group/ats-lang-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ats-lang-users/5588e888-3904-46c6-b851-2c3548fa6f27%40googlegroups.com.

Reply via email to