Author Topic: Defining a LISP function  (Read 538 times)

0 Members and 1 Guest are viewing this topic.

Grrr1337

  • Swamp Rat
  • Posts: 631
Re: Defining a LISP function
« Reply #15 on: October 08, 2018, 07:15:05 AM »
Once again, thank you gile!
Posts here are extremely useful for a lisper that decides to (atleast partially) transit into .NET

BTW I've heard before about the common naming convension in C# (more precisely in this (Bulgarian) lecture at 27:00),
but for me regardless of being aware of it, alot of coding practice is required (which I currently don't have for C#) to apply some standard (so apologies).
I find the link you posted is alot easier to follow (because its a quick do and do-not lecture).  8-)


Because the public property 'Dialog.arrayDGV' is never instantiated.

Ah now I see, Can you specify
was it because I messed-up the case: ArrayDGV with arrayDGV
or it didn't instantiated, because I used it as instance within that same class (... = new ...) -

Code - C#: [Select]
  1. ArrayDGV = new string[dataGridView1.Rows.Count, dataGridView1.Columns.Count];


Sorry again for my late reply (draughtsman work appeared).

gile

  • Water Moccasin
  • Posts: 2166
  • Marseille, France
Re: Defining a LISP function
« Reply #16 on: October 08, 2018, 08:54:20 AM »
Ah now I see, Can you specify
was it because I messed-up the case: ArrayDGV with arrayDGV
or it didn't instantiated, because I used it as instance within that same class (... = new ...) -

No the case is only a convention, but as C# is case sensitive, respecting these naming conventions may help to avoid confusion between private fields, local variable and method parameters on one hand and public properties on the other hand.
The property didn't instantiate because because you never initialize it, you only declare and initialize a local variable with the same name within the btnOk_Click() method, this variable is unknown outside the method:
Code - C#: [Select]
  1. public partial class Dialog : Form
  2. {
  3.    // a public property  named arrayDGV is declared but is not initialized
  4.    public string[,] arrayDGV { get; }
  5.  
  6.    //...
  7.  
  8.    private void btnOk_Click(object sender, EventArgs e)
  9.    {
  10. // a local variable named arrayDGV is declared and initialized to a new instance of string[,]
  11. // this variable is local to the method and has nothing to do with same named property
  12.        string[,] arrayDGV = new string[dataGridView1.Rows.Count, dataGridView1.Columns.Count];
  13.        //...
  14.    }
  15. }


Basicaly, this is the way you use a private field (global variable within the class) and expose it outside the class with a public property:
Code - C#: [Select]
  1. public partial class Dialog : Form
  2. {
  3.    // a private field named arrayDGV is declared and not initialized
  4.    private string[,] arrayDGV;
  5.  
  6.    // a public property named ArrayDGV is declared and initialized to return the arrayDGV field value
  7.    public string[,] ArrayDGV
  8.    {
  9.        get { return arrayDGV; }
  10.    }
  11.  
  12.    //...
  13.  
  14.    private void btnOk_Click(object sender, EventArgs e)
  15.    {
  16. // the private field named arrayDGV is initialized to a new instance of string[,]
  17.        arrayDGV = new string[dataGridView1.Rows.Count, dataGridView1.Columns.Count];
  18.        //...
  19.    }
  20. }


Since C#3, a new syntax named 'auto-properties' allows to avoid declaring a private field (the private filed is effectively created when compiling in IL):
Code - C#: [Select]
  1. public partial class Dialog : Form
  2. {
  3.    // a public property named ArrayDGV is declared to be initialized from within the class (private set)
  4.    public string[,] ArrayDGV { get; private set; }
  5.  
  6.    //...
  7.  
  8.    private void btnOk_Click(object sender, EventArgs e)
  9.    {
  10. // the ArrayDGV property is initialized as a new instance of string[,]
  11.        ArrayDGV = new string[dataGridView1.Rows.Count, dataGridView1.Columns.Count];
  12.        //...
  13.    }
  14. }
Speaking English as a French Frog

Grrr1337

  • Swamp Rat
  • Posts: 631
Re: Defining a LISP function
« Reply #17 on: October 10, 2018, 05:06:56 PM »
you never initialize it, you only declare and initialize a local variable with the same name within the btnOk_Click() method, this variable is unknown outside the method

After carefully reading your post:
"Ah now I understand! (atleast I think so)"
By default the declaration of the variables is private, so they are localised within the class or method, where they were declared.
As you know in LISP we manually have to declare them for every separate function (respectively method) - so this brought my confusion,
expecting that all of the declared variables would be local for the class and public for all the methods within that class :facepalm:

Apologies for my C# incompetence.. ended up with these self-explanations :

Code - C#: [Select]
  1. // Newbie C# self-explanations
  2. public class MyClass
  3. {
  4.  private string MyString1 = "String1"; // private and can be accessed within any method of MyClass
  5.  string MyString2 = "String2"; // private by default and can be accessed within any method of MyClass
  6.  public MyString3 = "String3"; // public and can be accessed outside of MyClass
  7.  
  8.  // #stupid commenting
  9.  // the method is private, so logic follows that
  10.  // everything declared within it is local for the method,
  11.  // and since the method itself is private then all the properties are private
  12.  // #end stupid commenting
  13.  // !!! All of the above comments are false, since even if the method is public - one can just call it, and cannot access any inner properties or other methods !!!
  14.  private void TheMethod()
  15.  {
  16.    int MyInteger = 1;
  17.    // ...
  18.  }
  19.  // Meaning that you cannot do.. ' MyClass.TheMethod().MyInteger ' - it just doesn't make any sense!
  20.  // Simply said: one can just call the method - MyClass.TheMethod();
  21.  // Although you can make the method to return something
  22.  
  23.  // Although you can define inner objects as inner-class:
  24.  public class Building
  25.  {
  26.    // Declaring public properties for the 'Building' object:
  27.    public int Floors { get; set; }
  28.    public int Rooms { get; set; }
  29.  
  30.    // Default values can be set for the properties:
  31.    Floors = 2;
  32.    Rooms = 6;
  33.  
  34.    // Declaring public methods for the 'Building' object:
  35.    public void AddFloors ()
  36.    {
  37.      // ...
  38.    }
  39.  
  40.    public void AddRooms ()
  41.    {
  42.      // ...
  43.    }
  44.  
  45.  }
  46.  // So a sample call in the main would be (I think so, might be wrong):
  47.  /*
  48.     class Program
  49.   {
  50.       static void Main()
  51.       {
  52.           Building building1 = new Building;
  53.           Building.Floors = 6;
  54.           Building.Rooms = 24;
  55.           Console.WriteLine("building1 Floors = {0} Rooms = {1}", building1.Floors, building1.Rooms);
  56.       }
  57.   }
  58.   */
  59.  // But thats what I came up with,
  60.  // an example https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/objects
  61.  // of creating a object through class
  62.  /*
  63.   public class Person // NOTE: this class is outter (its not nested in 'MyClass')
  64.   {
  65.       public string Name { get; set; }
  66.       public int Age { get; set; }
  67.       public Person(string name, int age)
  68.       {
  69.           Name = name;
  70.           Age = age;
  71.       }
  72.       //Other properties, methods, events...
  73.   }
  74.   */
  75.  // So a sample call in the main would be :
  76.  /*
  77.     class Program
  78.   {
  79.       static void Main()
  80.       {
  81.           Person person1 = new Person("Leopold", 6); // SEE THE DIFFERENCE? ALL THE PROPERTIES WERE SET WITHIN THE METHOD CALL
  82.           Console.WriteLine("person1 Name = {0} Age = {1}", person1.Name, person1.Age);
  83.       }
  84.   }
  85.   */
  86.  
  87. }
 
Although I might be wrong somewhere in my statements (if so, correct me please)... but in the end looks like I have alot of reading and C# coding to do.
Really appreciate your help, gile!


Just one last general question for you - as being both: a LISP and .NET developer: (no offense to the other developers like gile)
If in LISP one could create a list, that could contain other lists or any type of mixed data, for instance:
'((<point1> <string1> <object1>)(<point2> <string2> <object2>)...(<pointN> <stringN> <objectN>))
...and you could map a custom function to every element of the list... (or just do whatever you want with it)
What would be the alternative type of data for this in C# ?

I'm asking because of the required strict declaration, such as
Code - C#: [Select]
  1. string[] SingleStringArray
  2. string[,] ArrayOfStringArrays
Guessing, would it be an array of object instances, where you would store (<pointN> <stringN> <objectN>) as properties for each one?
And if it doesn't matter if its array or a C# list or an collection, then what is the most suitable to map via function(respectively method).

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9118
Re: Defining a LISP function
« Reply #18 on: October 10, 2018, 06:05:49 PM »
Without reading thread (only reading last post).
That would be a STRUCT.

Code - C#: [Select]
  1. public struct Cow  
  2. {  
  3.    public decimal weight;  
  4.    public string color;  
  5.    public string sex;  
  6. }


Public/Private ...welcome to the C based languages.
“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

gile

  • Water Moccasin
  • Posts: 2166
  • Marseille, France
Re: Defining a LISP function
« Reply #19 on: October 10, 2018, 06:33:54 PM »
The main difference between LISP and C# is about dynamic vs static typing.
This also one of the main issue when mixing both laguages (with the execution context).
The ResultBuffer (or the TypedValue array) provides a way to communicate between LISP and .NET when collections of different types instance are necessary. Each TypedValue embed a Value property (of type Object) and a TypeCode property (of type short) which allows to easily cast the object to its type.
Speaking English as a French Frog

MickD

  • Gator
  • Posts: 3145
  • I don't need a job, I need Money!!
Re: Defining a LISP function
« Reply #20 on: October 11, 2018, 12:21:36 AM »
Without reading thread (only reading last post).
That would be a STRUCT.

Code - C#: [Select]
  1. public struct Cow  
  2. {  
  3.    public decimal weight;  
  4.    public string color;  
  5.    public string sex;  
  6. }


Public/Private ...welcome to the C based languages.


I haven't read the whole thread either but the crux of Lisp<->.net/C/C++ interop is just marshalling data using resbuf's (ResultBuffer in C#) as one parameter rather than many parameters, the rest is just a function call passing the data to the called function at either end. This called function can use this data and if required it then needs to build the result buffer with the results to return the values.
COM is similar but much more involved just to save building resbuf types of structures to marshall data back and forth but that's what's going on under the hood.

If you think of it like that it's easy :)
"A language that doesn’t have everything is actually easier to program in than some that do."

        — Dennis M. Ritchie

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9118
Re: Defining a LISP function
« Reply #21 on: October 11, 2018, 07:26:09 AM »
Yeah I noticed that, guys. I guess I should have read the title of the thread too. I thought he was asking a different question at the end about lists in Lisp vs C# -ie. how you can "mix data types" in lisp but not C#. I apologize for my drive-by answer (next time it will be to issue a cat call).
“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

Grrr1337

  • Swamp Rat
  • Posts: 631
Re: Defining a LISP function
« Reply #22 on: October 11, 2018, 06:35:49 PM »
Without reading thread (only reading last post).
That would be a STRUCT.

Code - C#: [Select]
  1. public struct Cow  
  2. {  
  3.    public decimal weight;  
  4.    public string color;  
  5.    public string sex;  
  6. }


Public/Private ...welcome to the C based languages.

Thanks John,
If I properly understood I could create an array of struct instances and manipulate all of them within an iteration.
So respectively a (sub)list with items that stand for different properties, in C# thats a customly defined object with a customly defined properties/methods.
Well.. you know LISP aswell so you know from what mindset I'm switching to here.. (<mapcar_in_C#> 'MyMethod <Array/List/Collection>) :)



The main difference between LISP and C# is about dynamic vs static typing.

Ater I discovered for myself the static typing, started realising the fact -
That one could create a custom list, that can contain any variables aswell other lists..
so it could end up as uneven hierarchy of variables is now mind-blowing for me. i.e.:
Code - Auto/Visual Lisp: [Select]
  1. '(0 2 "string" (123 nil <object> "I define" (("whatever") "I") "want" <function> (34 PI)))
After John's reply I now imagine that such random hierarchical structure of variables
would be possible to create in C# by defining classes/objects/methods (afterall C# is a OOP language <DUH>)
I brought that question from Reply #17, because afterall I'm comming from a dynamic typing language (if I blank-started a static type of langugage I probably wouldn't imagine such fancy structures soon)



This also one of the main issue when mixing both laguages (with the execution context).

Trying to work on that one,
At the moment I think a good practice for me would be working on a console application project,
where I add few Class(es) as separate .cs files and test how I'd print out different variables in the main.
Still would accept any other advises regarding on "how to understand the execution context in VS".



The ResultBuffer (or the TypedValue array) provides a way to communicate between LISP and .NET when collections of different types instance are necessary. Each TypedValue embed a Value property (of type Object) and a TypeCode property (of type short) which allows to easily cast the object to its type.


I haven't read the whole thread either but the crux of Lisp<->.net/C/C++ interop is just marshalling data using resbuf's (ResultBuffer in C#) as one parameter rather than many parameters, the rest is just a function call passing the data to the called function at either end. This called function can use this data and if required it then needs to build the result buffer with the results to return the values.
COM is similar but much more involved just to save building resbuf types of structures to marshall data back and forth but that's what's going on under the hood.

If you think of it like that it's easy :)

Now its more clear what gile did in his demo codes, thank you guys for the resume explanations!


I thought he was asking a different question at the end about lists in Lisp vs C# -ie. how you can "mix data types" in lisp but not C#. I apologize for my drive-by answer (next time it will be to issue a cat call).

Well you thought right, John.. and its not you -
I must apologise for the additional questions, its because one thought of mine led to another, and you guys are so generous answering so I felt lucky!
For short: redirected so much from the topic question that I ended up asking on how to bridge the gap LISP<->.NET

.. or just to get rid off some of the LISP limitations ... (first one was the datagridview) ..next one would be to prompt like this:

Which is far more effective user prompt than my GetStringList - with DCL

Didn't think I would push-off that soon without gile's help in here!

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9118
Re: Defining a LISP function
« Reply #23 on: October 12, 2018, 09:42:14 AM »
Speaking in C language terms; you don't have to mapcar over a list like you do in Lisp. You can access objects (like the struct example) directly. [Cow.weight] However, you can create a list of Cows and use a foreach to iterate each cow object and pull the weight from each cow.

Speaking in C# in language `bridge mode'; when trying to share data between interfaces you need a middle-man and the word `bridge' you used is a pretty good analogy. The bridge is the ResultBuffer gile and MickD are talking about. In generic terms, not all datatypes can be shared as they are, often times they need to be TYPECAST back to their native container. That is to say, imagine that a NUMBER in C# cannot be "understood" by Lisp so you'd have to convert the NUMBER to STRING for sharing and back again to NUMBER again later.

This post was very generic and full of holes but I think it begins to answer some of your questions. I'll try again in a bit. Have you read any "learning C(plus, sharp, etc)" books? I'm thinking, these books will introduce you to the OO world, Data types, Inheritance, etc. a lot better then we can.
“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

gile

  • Water Moccasin
  • Posts: 2166
  • Marseille, France
Re: Defining a LISP function
« Reply #24 on: October 12, 2018, 12:55:12 PM »
The C# equivalent function for mapcar is: IEnumerable<T>.Select() Linq extension method.
All instances of classes deriving from IEnumerable<T> contains elements of the same type (T) as a LISP list used with mapcar has to contain only elements of the type required by the function passed as argument.

Code - C#: [Select]
  1. var lst = new[] { 1, 2, 3, 4 };
  2. lst.Select(x => x * x).ToArray()
  3.  
returns: int[4] { 1, 4, 9, 16 }

Code - Auto/Visual Lisp: [Select]
  1. (setq lst '(1 2 3 4))
  2. (mapcar '(lambda (x) (* x x)) lst)
returns (1 4 9 16)
Speaking English as a French Frog

MickD

  • Gator
  • Posts: 3145
  • I don't need a job, I need Money!!
Re: Defining a LISP function
« Reply #25 on: October 12, 2018, 05:46:43 PM »
Speaking in C language terms; you don't have to mapcar over a list like you do in Lisp. You can access objects (like the struct example) directly. [Cow.weight] However, you can create a list of Cows and use a foreach to iterate each cow object and pull the weight from each cow.
...

To further this point a bit:

A result buffer is a struct type in C that holds 3 values:
A result buffer Type (typecode) and the value. The type code is used so the when C gets it it knows what type of value to cast the rusbuf value to. This way you don't try to cast an Int to a String etc.
The other value is a pointer to the next resbuf which enables you to create a Linked List of resbuf's and make them as long as you like and each value can be different. The way this is done in C is by using a Union, this gives the resbuf the memory size of the largest possible value in the union to make memory management easier.
To iterate over the linked list you just call resbuf->next().

Now, to pass values back and forth between Lisp and C say, you only need one generic function in the interpreter that takes the name of the function and the resbuf parameter (which is the start of the linked list). The interpreter looks up the function name in a symbol table (Dictionary of string to function pointer) for that function and passes the resbuf to it with the call.

This is a simplification but it's a pretty elegant way to interop between the two languages. The trick is to realise that the Lisp interpreter is written in C and has many helper functions to help with all this and in the end your Lisp code is executed in C (albeit a lot slower due to the read/eval process etc.). The same thing happens with .Net languages but there needs to but the .Net lang sits in between Lisp and C so wrappers need to be written.
These wrappers are already written in the .Net API and look a lot different to the C version but are more idiomatic to .Net (OOP) to make them easier to use.
"A language that doesn’t have everything is actually easier to program in than some that do."

        — Dennis M. Ritchie

nullptr

  • BricsCAD
  • Needs a day job
  • Posts: 6767
  • AKA Daniel
Re: Defining a LISP function
« Reply #26 on: October 13, 2018, 11:50:44 PM »
search for Tony T's  TypedValueList, its handy... also you can add implicit conversion operators to your classes

Code - C#: [Select]
  1. namespace Commands
  2. {
  3.    class TypedValueList : List<TypedValue>
  4.    {
  5.        public static implicit operator ResultBuffer(TypedValueList src)
  6.        {
  7.            return new ResultBuffer(src.ToArray());
  8.        }
  9.    }
  10.  
  11.    class foo
  12.    {
  13.        double m_dval;
  14.        string m_sval;
  15.  
  16.        public foo(double index, string value)
  17.        {
  18.            DVal = index;
  19.            SVal = value;
  20.        }
  21.  
  22.        public double DVal
  23.        {
  24.            get { return m_dval; }
  25.            set { m_dval = value; }
  26.        }
  27.        public string SVal
  28.        {
  29.            get { return m_sval; }
  30.            set { m_sval = value; }
  31.        }
  32.  
  33.        public static implicit operator ResultBuffer(foo src)
  34.        {
  35.            return (TypedValueList)src;
  36.        }
  37.  
  38.        public static implicit operator TypedValueList(foo src)
  39.        {
  40.            return new TypedValueList()
  41.            {
  42.                new TypedValue((int)LispDataType.ListBegin),
  43.                new TypedValue((int)LispDataType.Double, src.DVal),
  44.                new TypedValue((int)LispDataType.Text, src.SVal),
  45.                new TypedValue((int)LispDataType.ListEnd)
  46.            };
  47.        }
  48.  
  49.    }
  50.  
  51.    public class Commands
  52.    {
  53.        [LispFunction("doit")]
  54.        public static ResultBuffer doit(ResultBuffer args)
  55.        {
  56.            return new foo(1.0, "hello world");
  57.        }
  58.    }
  59. }
  60.