imatix / gsl

iMatix GSL code generator
http://www.imatix.com
GNU General Public License v3.0
538 stars 107 forks source link

List library #66

Open canercandan opened 9 years ago

canercandan commented 9 years ago

Something that I am quite familiar with other languages such as C++ or Python is the use of list or vector container. I saw on GSL one can use XML data structure instead of that, but sometimes it is even more efficient and reduces drastically code length using a list mechanism since XML can be much more seen as map or dictionary than a single list container.

Therefore, I created a small library of functions that implements functions for such a purpose here is the list of these functions:

It is also possible to add a list into another. Here is a GSL script showing a typical usage:

.template 0

l1 = list_new()
l2 = list_new()

list_append(l2, 'aaa')
list_append(l2, 'zzz')

list_append(l1, l2)
list_append(l1, 'bbb')
list_append(l1, 'ccc')

define l2.dummy = 12
list_append(l2, 'www')

list_append(l1, l2)
list_append(l1, 'ddd')
list_append(l1, 'eee')
list_append(l1, 'fff')

list_delete(l1, 0)

list_print(l1)

echo list_get(l1, 1)

.endtemplate

And the result:

gsl/4 M: [[aaa,zzz],ccc,[aaa,zzz,www],ddd,eee,fff]
gsl/4 M: ccc

I don't know if anyone see useful to add them as a builtin GSL feature.

Anyway, here is the source code:

.template 0

function global.check_arg_missing(ctx, key, value)
  if !defined(my.value)
    abort '[$(my.ctx:)] arg "$(my.key:)" is missing'
  endif
endfunction

function global.list_new
  return XML.new('list')
endfunction

function global.list_exists(list)
  check_arg_missing('list_exists', 'list', my.list)

  return name(my.list)?"" = "list"
endfunction

function global.list_empty(list)
  check_arg_missing('list_exists', 'list', my.list)

  return !defined(my.list->.)
endfunction

function global.list_append(list, item)
  check_arg_missing('list_append', 'list', my.list)
  check_arg_missing('list_append', 'item', my.item)

  if list_exists(my.item)
    copy my.item to my.list as list
  else
    new my.list.item as i
      define i. = my.item
    endnew
  endif
endfunction

function global.list_get(list, i)
  check_arg_missing('list_get', 'list', my.list)
  check_arg_missing('list_get', 'i', my.i)

  for my.list. as ii where item() = my.i+1
    return ii
  else
    abort '[list_get] no item found @ $(my.i:)'
  endfor
endfunction

function global.list_delete(list, i)
  check_arg_missing('list_delete', 'list', my.list)
  check_arg_missing('list_delete', 'i', my.i)

  my.item = list_get(my.list, my.i)
  delete my.item
endfunction

function global.list_foreach(list, callback, record)
  check_arg_missing('list_foreach', 'list', my.list)
  check_arg_missing('list_foreach', 'callback', my.callback)

  my.record ?= XML.new('record')

  for my.list. as i
    $(my.callback)(i, my.record)
  endfor

  return my.record
endfunction

function print_callback(item, record)
  check_arg_missing('print_callback', 'item', my.item)
  check_arg_missing('print_callback', 'record', my.record)

  if list_exists(my.item)
    my.sublist_record = list_foreach(my.item, 'print_callback')
    copy my.sublist_record to my.record
  else
    new my.record.field as f
      define f. = my.item.
    endnew
  endif
endfunction

function recursive_print(record)
  check_arg_missing('recursive_print', 'record', my.record)

  my.s = "["

  for my.record. as i
    if name(i)?"" = "record"
      my.s += recursive_print(i)
    else
      my.s += i.
    endif

    if !last(i)
      my.s += ','
    endif
  endfor

  my.s += "]"

  return my.s
endfunction

function global.list_print(list)
  check_arg_missing('list_print', 'list', my.list)

  my.record = list_foreach(my.list, 'print_callback')
  echo recursive_print(my.record)
endfunction

.endtemplate
jschultz commented 9 years ago

It wouldn't be terribly difficult to implement a new list object using a GXL file. You can probably do a bit of reverse engineering by looking at the existing GSL files, and the ggfunc.gsl script that processes GXL files into C. As I wrote this code (many years ago) I can probably give a hand or advice.

Cheers, Jonathan

On 14/12/14 04:31, Caner Candan wrote:

Something that I am quite familiar with other languages such as C++ or Python is the use of list or vector container. I saw on GSL one can use XML data structure instead of that, but sometimes it is even more efficient and reduces drastically code length using a list mechanism since XML can be much more seen as map or dictionary than a single list container.

Therefore, I created a small library of functions that implements functions for such a purpose here is the list of these functions:

  • list_new: create a new list
  • list_exists: check if the passed argument is a list
  • list_empty: does the list empty ?
  • list_append: append a new item into the list
  • list_get: get the i^th item of the list
  • list_delete: delete the i^th item of the list
  • list_foreach: apply a callback function to every single item in the list
  • list_print: standard output the whole list

It is also possible to add a list into another. Here is a GSL script showing a typical usage:

|.template 0

l1 = list_new() l2 = list_new()

list_append(l2, 'aaa') list_append(l2, 'zzz')

list_append(l1, l2) list_append(l1, 'bbb') list_append(l1, 'ccc')

define l2.dummy = 12 list_append(l2, 'www')

list_append(l1, l2) list_append(l1, 'ddd') list_append(l1, 'eee') list_append(l1, 'fff') list_delete(l1, 0) list_print(l1) echo list_get(l1, 1)

.endtemplate |

And the result:

18:25:32: gsl/4 M: [[aaa,zzz],ccc,[aaa,zzz,www],ddd,eee,fff] 18:25:32: gsl/4 M: ccc

I don't know if anyone see useful to add them as a builtin GSL feature.

Anyway, here is the source code:

|.template 0

function global.check_arg_missing(ctx, key, value) if !defined(my.value) abort '[$(my.ctx:)] arg "$(my.key:)" is missing' endif endfunction

function global.list_new return XML.new('list') endfunction

function global.list_exists(list) check_arg_missing('list_exists', 'list', my.list)

return name(my.list)?"" = "list" endfunction

function global.list_empty(list) check_arg_missing('list_exists', 'list', my.list)

return !defined(my.list->.) endfunction

function global.list_append(list, item) check_arg_missing('list_append', 'list', my.list) check_arg_missing('list_append', 'item', my.item)

if list_exists(my.item) copy my.item to my.list as list else new my.list.item as i define i. = my.item endnew endif endfunction

function global.list_get(list, i) check_arg_missing('list_get', 'list', my.list) check_arg_missing('list_get', 'i', my.i)

for my.list. as ii where item() = my.i+1 return ii else abort '[list_get] no item found @ $(my.i:)' endfor endfunction

function global.list_delete(list, i) check_arg_missing('list_delete', 'list', my.list) check_arg_missing('list_delete', 'i', my.i)

my.item = list_get(my.list, my.i) delete my.item endfunction

function global.list_foreach(list, callback, record) check_arg_missing('list_foreach', 'list', my.list) check_arg_missing('list_foreach', 'callback', my.callback)

my.record ?= XML.new('record')

for my.list. as i $(my.callback)(i, my.record) endfor

return my.record endfunction

function print_callback(item, record) check_arg_missing('print_callback', 'item', my.item) check_arg_missing('print_callback', 'record', my.record)

if list_exists(my.item) my.sublist_record = list_foreach(my.item, 'print_callback') copy my.sublist_record to my.record else new my.record.field as f define f. = my.item. endnew endif endfunction

function recursive_print(record) check_arg_missing('list_print', 'record', my.record)

my.s = "["

for my.record. as i if name(i)?"" = "record" my.s += recursive_print(i) else my.s += i. endif

 if !last(i)
   my.s += ','
 endif

endfor

my.s += "]"

return my.s endfunction

function global.list_print(list) check_arg_missing('list_print', 'list', my.list)

my.record = list_foreach(my.list, 'print_callback') echo recursive_print(my.record) endfunction

.endtemplate |

— Reply to this email directly or view it on GitHub https://github.com/imatix/gsl/issues/66.