> On 11 Jun 2019, at 09:50, Yanghao Hua <yanghao...@gmail.com> wrote:
> 
> On Mon, Jun 10, 2019 at 8:57 PM Caleb Donovick <donov...@cs.stanford.edu 
> <mailto:donov...@cs.stanford.edu>> wrote:
>> 
>> First off, I have admittedly not read all of this thread.  However, as 
>> designer of DSL's in python, I wanted to jump in on a couple of things I 
>> have seen suggested.  Sorry If I am repeating comments already made.  Over 
>> the last few years I have thought about every suggestion I have seen in this 
>> thread and they all don't work or are undesirable for one reason or another.
> 
> Glad to see I am not alone in the woods :-) So the argument that this
> problem is only Yanghao -- a single person's problem -- can be gone.
> You have to rephrase it to "this is only two person's problem" now.
> ;-)

Some times a DSL is usable within the python syntax and that is great.
I have use python for a number of DSL's.

But when the DSL is beyond what python can help with directly I'm wondering
why you do not parse the DSL with python and execute the results.

In that way you can have any semantics that you want from any syntax that you
wish to have. However you do not need the python language to be changed at all.

And it must be clear that you are making little to no progress on convincing 
people
that changing python is a good idea.

Barry


> 
>> Regarding what code will become simpler if an assignment operator was 
>> available.  I currently walk the AST to rewrite assignments into the form I 
>> want.  This is code is really hard to read if you are not familiar with the 
>> python AST, but the task it is performing is not hard to understand at all 
>> (replace assignment nodes with calls to a function call to 
>> dsl_assign(target_names, value, globals(), locals()).  The dsl_assign 
>> function basically performs some type checking before doing the assignment.  
>> Once again the code is much harder to understand than it should be as it 
>> operates on names of variables and the globals / locals dictionaries instead 
>> of on the variables themselves.  Also to get the hook into the AST I have to 
>> have use an importer which further obscures my code and makes use kinda 
>> annoying as one has to do the following:
>> ```
>> main.py:
>> import dsl # sets up the importer to rewrite the AST
>> import dsl_code # the code which should morally be the main but most be 
>> imported after dsl
>> ```
>> Granted anything in a function or a class can be rewritten with a decorator 
>> but module level code must be rewritten by an importer.
> 
> I thought about doing it a lot ... eventually manipulating AST is not
> so much easier than actually re-develop the entire DSL from scratch
> ... and this suffers eventually similar isssues like @=/L[:]
> overriding, it abuses a common understanding. I have also been looking
> into MacroPy3 for some time now, and despite you still need something
> like P[your customized expression] (the P[...] overhead which is
> exposed to end-users), changing an existing python syntax to mean
> something completely different, or translating a non-exist python
> syntax into something else really makes me feel this will make things
> mentally inconsistent, and actually makes python no longer python ...
> And this haven't touched what it means for debugging later on ...
> 
>> The problem with overloading obj@=value:
>> As Yanghao have pointed out @ comes with expectations of behavior.  Granted 
>> I would gamble most developers are unaware that @ is python operator but it 
>> still has meaning and as such I don't like abusing it.
> 
> Yep.
> 
>> The problem with using obj[:]=value:
>> Similar to @ getitem and slices have meaning which I don't necessarily want 
>> to override. Granted this is least objectionable solution I have seen 
>> although, it creates weird requirements for types that have __getitem__ so 
>> it can just be used by inheriting `TypedAssignment` or something similar.
> 
> Exactly. I will try to summarize all the pros and cons I saw people
> posting for the L[:] case, and the thing for DSL is L[:] is confusing
> on its own (not better than obj.next = ...).
> 
>> The problem with descriptors:
>> They are hard to pass to functions, for example consider trying to fold 
>> assignment.
>> ```
>> signals = [Signal('x'), Signal('y'), Signal('z')]
>> out = functools.reduce(operator.iassign, signals)
>> ```
>> vs
>> ```
>> signals = SignalNamespace()
>> signal_names =  ['x', 'y', 'z']
>> out = functools.reduce(lambda v, name: settattr(signals, name, v))
>> ```
>> In general one has to pass the name of the signal and the namespace to a 
>> function instead the signal itself which is problematic.
>> 
>> The problem with exec:
>> First off its totally unpythonic, but even if I hide the exec with importer 
>> magic it still doesn't give me the behavior I want.
>> Consider the following
>> ```
>> class TypeCheckDict(dict, MutableMapping): # dict needed to be used as 
>> globals
>>  """
>>  Dictionary which  binds keys to a type on first assignment then type checks 
>> on future
>>  assignement. Will infer type if not already bound. """
>>  __slots__ = '_d'
>>  def __init__(self, d=_MISSING):
>>    if d is _MISSING:
>>      d = {}
>>    self._d = d
>> 
>>  def __getitem__(self, name):
>>    v = self._d[name][1]
>>    if v is _MISSING:
>>      raise ValueError()
>>    else:
>>      return v
>> 
>>  def __setitem__(self, name, value):
>>    if name not in self._d:
>>      if isinstance(value, type):
>>        self._d[name] = [value, _MISSING]
>>      else:
>>        self._d[name] = [type(value), _MISSING]
>>      elif isinstance(value, self._d[name][0]):
>>        self._d[name][1] = value
>>      else:
>>        raise TypeError(f'{value} is not a {self._d[name][0]}')
>> 
>>  # __len__ __iter__ __delitem__ just dispatch to self._d
>> 
>> S = '''
>> x = int
>> x = 1
>> x = 'a'
>> '''
>> exec(S, TypeCheckDict(), TypeCheckDict()) # raises TypeError 'a' is not a int
>> 
>> S = '''
>> def foo(): # type of foo inferred
>>  x = int
>>  x = 'a'
>> foo()
>> '''
>> exec(S, TypeCheckDict(), TypeCheckDict()) # doesn't raise an error as a 
>> normal dict is used in foo
>> ```
> 
> Python provides us all the flexibility to do all kinds of "fancy"
> things, so flexible that we can make it *NOT* look like python at all.
> I have done similar things for descriptors, and I am still thinking
> was it the right approach to make descriptor not behaving like the way
> a descriptor is supposed to behave.
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org 
> <mailto:python-ideas@python.org>
> To unsubscribe send an email to python-ideas-le...@python.org 
> <mailto:python-ideas-le...@python.org>
> https://mail.python.org/mailman3/lists/python-ideas.python.org/ 
> <https://mail.python.org/mailman3/lists/python-ideas.python.org/>
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/UHSLG7JWXXRRAXS2JCFKV656TFO3QRUE/
>  
> <https://mail.python.org/archives/list/python-ideas@python.org/message/UHSLG7JWXXRRAXS2JCFKV656TFO3QRUE/>
> Code of Conduct: http://python.org/psf/codeofconduct/ 
> <http://python.org/psf/codeofconduct/>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/W5SQAPRHKVANVRY3Y6QQ6763AB7D5O6F/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to