mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.49k stars 1.59k forks source link

Appending to array inside dictionary #3931

Open barsoosayque opened 6 years ago

barsoosayque commented 6 years ago

Hello ! Love the dictionary feature, however It seems that I can't add new values to the array inside of the dictionary. I am trying to ensure that the user selected available build options for the platform, and to do so I populate supported_backends.get('video') with platform-specific video backends darwin_supported_backends.get('video'), both dictionary values are arrays. Here is code snippet:

darwin_supported_backends = { 
  'video': [ 'opengl4', 'metal' ], 
  'audio': [ 'openal' ] 
  }
supported_backends = { 'video': [], 'audio': [] }

if build_machine.system() == 'darwin'
  supported_backends.get('video') += darwin_supported_backends.get('video')
  supported_backends.get('audio') += darwin_supported_backends.get('audio')
endif

And here is the build log (with omitted path, I hope it's ok to do that):

The Meson build system
Version: 0.47.1
Source dir: <path>
Build dir: <path>/build
Build type: native build
meson.build:225:21: ERROR:  Plusassignment target must be an id.
  supported_backends.get('video') += darwin_supported_backends.get('video')
                     ^
A full log can be found at <path>/build/meson-logs/meson-log.txt

I found nothing regarding this in the documentation, so not sure if I'm doing something wrong and this is intended behavior.

jpakkane commented 6 years ago

This is the intended behaviour. All objects are immutable, you can not change the contents of them. You can only create new ones. (which is what += does behind the scenes). Once #3905 lands you should be able to do something like:

update = {'key': d['key'] + ['new_thing']}
d += update
barsoosayque commented 6 years ago

Oh, I see. I was asking because the following:

foreach type, list : supported_backends
  if type == 'video'
    list += darwin_supported_backends.get('video')
  elif type == 'audio'
    list += darwin_supported_backends.get('audio')
  endif
endforeach

is working quite well. So I was curious if I could shorten the code !

nirbheek commented 6 years ago

is working quite well.

Is it? Because I tested it and it doesn't:

backends = {'video': ['foo'], 'audio': ['bar']}

message(backends)
foreach type, list : backends
  message(list)
  if type == 'video'
    list += ['faz']
  else
    list += ['baz']
  endif
  message(list)
endforeach
message(backends)

Outputs this:

Message: {'video' : ['foo'], 'audio' : ['bar']}
Message: ['foo']
Message: ['foo', 'faz']
Message: ['bar']
Message: ['bar', 'baz']
Message: {'video' : ['foo'], 'audio' : ['bar']}

So += on list actually creates a new list, and does not edit the original list in backends.

barsoosayque commented 6 years ago

Yes, @nirbheek you are totally right. I hurried to conclusions 😓. I assumed that if it's syntactically correct, then it is working for sure. My bad. Just gonna wait for that PR to land.

But now I guess I only can solve the issue by using multiple variables instead of the dictionary.