Documentos de Académico
Documentos de Profesional
Documentos de Cultura
3. Tipos
3.1 tipos primitivos
3.2 Tipos definidos por el usuario
3.3 Colecciones
3.3.1 Lista
3.3.1.1 Rango
3.3.1.2 Indexación
3.3.1.3 lista dinámica
3.3.1.4 Lista de inmutabilidad
3.3.2 Reglas de
3.4 conversión de tipo de
diccionario 3.4.1 Caso sin
matriz 3.4.2 Promoción de rango
4. Variables
4.1 Alcance
4.2 dinámico
4.2.1 Resolución de alcance
5. Funciones
5.1 Declaración de función
5.2 Argumentos predeterminados
6. Expresiones
6.1 Expresión de creación de listas
6.2 Expresión de rango Expresión
6.3 condicional en línea 6.4 Expresión
de acceso a miembros Expresión de acceso a
6.5 listas Operadores 6.6.1 Operadores
6.6 aritméticos 6.6.2 Operadores de
comparación
Machine Translated by Google
8. Bloques de idioma
8.1 Bloque de idioma asociativo por defecto
8.2 Bloque de idioma asociativo anidado Bloque
8.3 de idioma imperativo 9. Replicación y guía
de replicación Guía de replicación y replicación Regla de
9.1 despacho de funciones para replicación y
9.2 guía de replicación
10. List@Level 11.
Funciones integradas
12. Internos
12.2.4 Propiedades
12.2.5 Funciones miembro
12.2.6 Modificadores de acceso
12.2.7 Miembros estáticos
1. Introducción
Esta es la documentación para el lenguaje de programación DesignScript. DesignScript es un lenguaje dinámico, de
recolección de elementos no utilizados y asociativo, y proporciona un sólido soporte para una programación basada en flujos.
ambiente.
1
La gramática en esta especificación está en forma extendida de Backus-Naur (EBNF).
Este documento no contiene información sobre las API y la interfaz de funciones externas (métodos Zero Touch). Este último
depende de la implementación.
2. Elementos léxicos
2.1. Comentarios
DesignScript admite dos tipos de comentarios.
Ejemplo:
/*
Bloquear comentarios
*/
y = 2;
2.3. Identificadores
Los identificadores en DesignScript nombran variables, tipos, funciones y espacios de nombres.
Identificador =
identificador_inicial_letra {identificador_parte_letra}
1
https://en.wikipedia.org/wiki/Extended_Backus-Naur_Form
Machine Translated by Google
“identifier_part_letter” es el carácter Unicode en las categorías de “identifier_start_letter” que incluye las siguientes categorías: •
Letra combinada (Mn, Mc) • Letra digital decimal (Nd) • Letra de conexión (Nc) • No ensamblador de ancho cero
romper, clase, constructor, continuar, def, más, más si, extiende, para, desde, si, importar, en,
devolver, estático, mientras,
verdadero Falso
dígito = '0'..'9'
Ejemplo:
123;
punto_flotante =
dígito { dígito } '.' [dígito { dígito }] [exponente]
Machine Translated by Google
Ejemplo:
1.2e3; // 1200.0;
1.234;
0,123;
cadena representa una constante de cadena. Se obtiene poniendo una secuencia de caracteres entre comillas dobles (“).
Cualquier carácter puede estar en la secuencia excepto la nueva línea y las comillas dobles ("). El carácter de barra invertida en la secuencia podría
2
combinarse con el siguiente carácter para convertirse en un carácter de escape:
• \a •
\b • \f
• \n •
\t • \v
• \r
Ejemplo:
3. Tipos
orientado a objetos, lo que significa que la verificación de tipos de un programa se realiza en tiempo de ejecución en función de los datos devueltos.
“”
cadena n/A
2
https://en.wikipedia.org/wiki/Escape_character Estos
*
son detalles de implementación y no son específicos de la especificación del idioma.
Machine Translated by Google
entero 63 -2 63 - 2 - 1 0
Si la implementación del idioma es compatible con FFI (funciones externas), el valor predeterminado de todos los demás tipos de FFI
importados es 'nulo'.
3.3. Colecciones
3.3.1. Lista
Una lista es un tipo de variable que contiene uno o más valores de un tipo dado o una variedad de tipos. También puede contener
valores que son Listas por sí mismos o Diccionarios. Puede considerarse como una matriz dinámica cuyo tamaño no es fijo y se asigna
en tiempo de ejecución. Las listas se crean con el operador de corchetes ([ ]) alrededor de un conjunto de valores separados por comas,
o se dejan vacías para crear una colección vacía:
3
https://en.wikipedia.org/wiki/Double-precision_floating-point_format
Machine Translated by Google
3.3.1.1. Rango
Si un tipo tiene corchetes, "[ ]", como sufijo después, declara una lista. El número de “[]” especifica el rango o la
dimensión de la lista. Un “[]..[]” especifica un rango arbitrario, lo que significa que la lista puede tener cualquier rango,
incluido un valor único o el rango 0. Por ejemplo:
Una lista es un tipo único en DesignScript, ya que es el único tipo que admite la replicación. Las funciones pueden
replicarse sobre argumentos de lista. El rango de un tipo de argumento decide cómo funcionan la replicación y las
guías de replicación en el argumento durante el envío de la función.
3.3.1.2. Indexación Es
posible indexar en cualquier ubicación de la lista usando el operador de corchetes ([ ]) después del nombre de la
variable. La indexación comienza en 0, lo que significa que se accede al primer elemento de una lista 'a' con: 'a[0]'.
Las listas también se pueden usar como índices para generar nuevas sublistas a partir de una lista. Por ejemplo, una
lista que contiene los números [1, 3, 5, 7], cuando se usa como índice de una lista, extrae los elementos 2, 4, 6 y 8 de
una lista:
También es posible cambiar dinámicamente el rango de una lista. En el siguiente ejemplo, 'x' es originalmente una lista
de rango 1. Cuando se establece en un valor en un índice para una dimensión que excede el límite/rango de la lista, los
índices intermedios se establecen en valores 'nulos' debido al relleno nulo:
Machine Translated by Google
Nota: La naturaleza dinámica de una lista no debe confundirse con la inmutabilidad de la lista que se trata en el siguiente
sección.
Las listas en DesignScript son inmutables. Cuando se copia una lista de una variable a otra variable, se trata de una operación de
copia profunda, es decir, se copian también todos los elementos de la lista. Lo mismo ocurre cuando las listas de DesignScript
interactúan con las listas de C#. La lista original permanece inmutable y cualquier operación en ella crea una nueva Lista. Ejemplo:
a = 1..5; b
= un; b[7]
= 99; // b = [1, 2, 3, 4, 5, nulo, nulo, 99], a = [1, 2, 3, 4, 5]
3.3.2. Diccionario
Diccionario =
"{" valores clave? “}”
valoresclave
= valorclave (“,” valorclave)*
keyValue =
cadena “:” Expresión
Un diccionario DesignScript es un mapa desordenado de pares clave-valor, donde las claves son únicas en el diccionario y solo pueden
ser del tipo 'cadena'. Los valores en el Diccionario pueden ser de cualquier tipo, incluidas listas y diccionarios en sí mismos. Los
diccionarios se inicializan usando llaves, '{ }'. Las llaves vacías crean un diccionario vacío. Los diccionarios se pueden inicializar y
consultar utilizando la siguiente sintaxis:
A diferencia de las listas, los diccionarios no se pueden modificar dinámicamente una vez inicializados. Son estrictamente inmutables.
La replicación no es compatible con los diccionarios.
Machine Translated by Google
Dado que DesignScript es un lenguaje de tipo dinámico, los valores se pueden convertir entre diferentes tipos
automáticamente en tiempo de ejecución, lo que se conoce como coerción de tipo implícita. La conversión de
tipo implícita puede ocurrir con los valores cuando interactúan entre sí a través de operadores como '==' o
desencadenados por el contexto circundante, como con 'if (valor) {...}', donde 'valor' se convierte en booleano. La
conversión de tipo también ocurre con los argumentos de función cuando se pasan a posiciones de parámetro
con tipo en la función y se les obliga a asumir el tipo del parámetro. Ejemplos:
// Un valor doble distinto de cero se convierte en un valor verdadero cuando se fuerza a un 'bool'
escriba a = 3.0 == verdadero; // un = verdadero
// Una cadena se puede convertir a un valor verdadero cuando se fuerza a un tipo 'bool'. Vea la
siguiente declaración condicional en línea como ejemplo: i = “hola”? “no vacío” : “vacío”; // i = "no vacío"
i=
“”
? “no vacío” : “vacío”; // i = "vacío"
Las siguientes reglas implícitas de conversión de tipos especifican el resultado de convertir un objeto de un
tipo a otro con contenido similar:
variable
si si, si Sí, si Sí, si el tipo si, si Sí, si el tipo
es real el tipo real real puede es real real puede
el tipo puede puede ser ser obligado a el tipo puede ser obligado a
ser coaccionado a bool ser usuario definido
coaccionado doble coaccionado escribe
a int a la cadena
En t si si si x != 0 no no
bool si no no si no no
x!= “”
cadena si no no si no
a: int[] = 123; // a = [123] ya que el valor asignado a 'a' se promociona a una lista
Desde definido[]
variable
si Sí, si Sí, si Sí, si el tipo Sí, si Sí, si el tipo real
el tipo el tipo real real se el tipo coincide con el
real se se puede puede real se definido por el usuario
puede obligar a obligar a bool puede escribe
obligar duplicar forzar a
a int una cadena
En t si si si x != 0 no no
bool si no no si no no
x!= “”
cadena si no no si no
4. Variables
4.1. Dinámica
Las variables en DesignScript son dinámicas. Si una variable no se declara con un tipo, se le puede asignar
cualquier tipo y el tipo depende totalmente del tiempo de ejecución. Ejemplo:
En el siguiente ejemplo, dado que 'a' se declara como 'int' y no hay conversión de 'cadena' a 'int', 'a' es
'nulo' en este caso:
Machine Translated by Google
4.2. Alcance
4
DesignScript utiliza alcance de bloque. El alcance de una variable definida en DesignScript se limita a un bloque (como un bloque de
idioma) o una función donde se define. Una variable se puede usar antes de que se defina debido a la asociatividad y la máquina
virtual DesignScript se asegurará de propagar la actualización del valor a todas sus referencias.
En el caso del alcance imperativo, las declaraciones se ejecutan en secuencia a diferencia del código asociativo. Todas las
variables globales (definidas en el ámbito externo) que se utilizan en el bloque imperativo se copian localmente y cualquier cambio
en ellas dentro del bloque imperativo no afecta sus valores en el bloque externo. En otras palabras, estas variables globales son de
solo lectura (inmutables) dentro del bloque imperativo:
x = 1;
y = 2;
def foo(x) { z =
3; // “z” es una variable local
devuelve x + y; // "x" es el parámetro
// "y" está en el ámbito externo y no está definido dentro de la función
}
[Imperativo] { x =
3; m = norte; // Se hace una copia local de “x” y la “x” global no cambia // “m”, “n” son variables
n = 4; locales. // el orden de las declaraciones es importante en el código imperativo //
dado que 'm' se asigna antes que 'n', su valor sigue siendo 'nulo'
si es verdad) {
y = x + 100; // OK, "x" es visible aquí
}
devuelve x + y + m; // se hace una copia local de 'y' dentro del bloque imperativo
4
https://en.wikipedia.org/wiki/Scope_(informática_ciencia)#Block_scope
Machine Translated by Google
• El alcance global.
5. Funciones
5.1. Declaración de función
FunctionDeclaration =
identificador “def” [“:” TypeSpecification] ParameterList StatementBlock.
Lista de parámetros =
“(“ [Parámetro {“,” Parámetro}] “)”
Parámetro =
identificador [“:” TypeSpecification] [DefaultArgument]
BloqueDeDeclaraciones =
"{" { Declaración } "}"
El tipo de retorno de una función es opcional. De forma predeterminada, el tipo de retorno es una lista clasificada
arbitraria, "var[]..[]". Si se especifica el tipo de devolución, puede ocurrir una conversión de tipo. No se recomienda especificar el tipo
de retorno a menos que sea necesario.
Una función siempre debe definirse en el bloque de lenguaje asociativo global o en el bloque de nivel superior.
Para los parámetros, si no se especifican sus tipos, por defecto son del tipo 'var'. El tipo de parámetros debe
especificarse cuidadosamente para que la replicación y la guía de replicación funcionen como se desea.
Por ejemplo, si el tipo de un parámetro es var[]..[] (rango arbitrario), significa que no hay replicación en este parámetro.
Ejemplo:
devuelve x + y;
}
Ejemplo:
Machine Translated by Google
// es válido porque "y" y "z" son los parámetros predeterminados más a la derecha def foo(x, y =
1, z = 2) {
devuelve x + y + z;
}
devuelve x + y + z;
}
Ejemplo:
devuelve x + y;
}
volver x *
y;
}
Las sobrecargas de funciones, con la excepción de aquellas con parámetros que solo difieren por rango, son ilegales.
Esto significa que para las funciones sobrecargadas que tienen el mismo número y tipos de parámetros pero tienen uno
o más parámetros que difieren solo en el rango, la sobrecarga que se define primero siempre gana mientras que el
compilador descarta el resto. Por ejemplo,
Machine Translated by Google
// sobrecarga válida
El nodo de mayor rango se puede utilizar tanto en una llamada replicada como en una no replicada y, por lo tanto, siempre se
prefiere a una sobrecarga de menor rango. Por lo tanto, como regla general, siempre se aconseja a los usuarios que eliminen las
sobrecargas de menor rango en favor de métodos de mayor rango para que el compilador de DesignScript siempre llame al método
de mayor rango como el primero y único que encuentre.
• El alcance mundial
Como las funciones se pueden sobrecargar, el resultado de la resolución de funciones devolverá una lista de funciones candidatas.
La máquina virtual encontrará la mejor coincidencia según el tipo de argumentos, los tipos de parámetros y la guía de
replicación.
Machine Translated by Google
6. Expresiones
RangeExpression =
Expresión [“..” [“#”] Expresión [“..” [“#”] Expresión]
• valor_inicial..valor_final..incremento
• Si start_value < end_value, entonces el incremento debe ser un valor positivo. Va a
generar una lista que comience en valor_inicial y último valor <= valor_final, aumentando según el valor de
incremento especificado en la expresión de rango.
• Si valor_inicial > valor_final, el incremento debe ser un valor negativo. Va a
generar una lista que comienza en start_value last value >= end_value, disminuyendo por el valor de
incremento especificado en la expresión de rango. • start_value..#number_of_elements..increment: genera
una lista que contiene
número_de_elementos elementos. El elemento comienza en start_value y el incremento es incremento. El
valor de número_de_elementos siempre se redondea al entero más próximo.
• valor_inicial..valor_final..#número_de_elementos: genera una lista que contiene
number_of_elements elementos igualmente espaciados entre start_value y end_value,
incluidos start_value y end_value. Dependiendo de si start_value <= end_value, la lista
generada estará en orden ascendente o descendente. El valor de número_de_elementos siempre
se redondea al entero más próximo.
Machine Translated by Google
Ejemplo:
1..5; // [1, 2, 3, 4, 5]
5..1; // [5, 4, 3, 2, 1]
1..10..2; // [1, 3, 5, 7, 9]
10..1..-2; // [10, 8, 6, 4, 2]
1..#5..2; // [1, 3, 5, 7, 9]
1..5..#3; // [1, 3, 5]
La expresión de rango se maneja especialmente para cadenas con un solo carácter. Por ejemplo, las siguientes
expresiones de rango también son válidas:
Si se requiere que una expresión de rango generada comience y termine precisamente en los valores de expresión de
rango mínimo y máximo, podemos aproximar un incremento, acercándonos lo más posible al incremento y manteniendo
una distribución equitativa de números entre los límites del rango. Esto se puede hacer con el signo de tilde (~) antes del
tercer parámetro.
0..7..~0.75; // [0, 0.777, 1.555, 2.333, 3.111, 3.888, 4.666, 5.444, 6.222, 7]
La primera expresión en la expresión condicional en línea es expresión de condición cuyo tipo es bool. Si es cierto, el
valor de “?” se devolverá la cláusula; de lo contrario, se devolverá el valor de la cláusula ":". No es necesario que los tipos
de expresiones para las condiciones verdaderas y falsas sean iguales. Ejemplo:
Machine Translated by Google
x = 2;
y = (x % 2 == 0) ? “fu”: 21;
x = [verdadero, falso,
verdadero]; y = [“foo”, “bar”,
“qux”]; z = [“ding”, “dang”, “dong”];
xyz
"y" y "z" podrían ser propiedades o funciones miembro. Si no son accesibles, se devolverá nulo .
Ejemplo:
hacha]
“x” podría ser un valor entero o una clave de cualquier tipo (si “a” es un diccionario).
a = 1;
a[1] = 2; // “a” será promovido, a = [1, 2] ahora
Machine Translated by Google
+ Suma aritmética
- Resta aritmética
*
multiplicación aritmética
/ división aritmética
% modo aritmético
> comparación grande
>= Comparación grande que
< Comparar menos
<= Comparación menor que
== Comparación igual
!= Comparación no igual
&& lógico y
|| ! lógico o
No lógico
- Negar
Todos los operadores admiten la replicación. Excepto el operador unario “!”, todos los demás operadores también admiten la
guía de replicación. Es decir, los operandos podrían ser guías de replicación adjuntas.
x = [1, 2, 3]; y =
[4, 5, 6]; r1 = x + y;
// replicación // r1
= [5, 7, 9]
Precedencia Operador
-
6
5 *, /, %
4 +, -
Machine Translated by Google
2 &&
1 ||
+, -, *, /, %
Normalmente, los operandos son valores enteros o valores de punto flotante. "+" se puede utilizar como concatenación de cadenas:
s1 = “Diseño”; s2
= “Guión”; s = s1
+ s2; // “Script de diseño”
declaraciones que utilizan estos operadores dan como resultado un valor "verdadero" o "falso".
declaración que usa un operador lógico solo puede devolver un valor "verdadero" o "falso".
&&, ||, !
7. Declaraciones
instrucciones de importación importan otro archivo de código fuente de DesignScript o ensamblado de C# en el espacio de nombres actual.
Si importa un ensamblado de C#, la máquina virtual DesignScript generará clases de DesignScript para las clases definidas en el ensamblado,
Las declaraciones de importación podrían importar todas las entidades encontradas en la ubicación, o para una entidad nombrada específica
encontrada en la ubicación.
• Una ruta de archivo relativa, utilizando las convenciones del sistema operativo local. • Una
ruta de archivo absoluta, utilizando las convenciones del sistema operativo local.
• Una URI.
Ejemplo:
Tenga en cuenta que las declaraciones de importación solo se pueden usar en archivos DesignScript (con una extensión ".DS"), que se pueden
importar a Dynamo. Las declaraciones de importación no se pueden usar en nodos de bloque de código en Dynamo.
7.4. asignaciones
El lado izquierdo de “=” debe ser asignable. Por lo general, es una expresión de acceso a miembros o una expresión o variable de acceso a una
matriz . Si el lado izquierdo es una variable que no se ha definido antes, la declaración de asignación definirá esta variable.
2. Una declaración de ruptura en el bloque de la declaración for o while en el bloque de lenguaje imperativo.
3. Una declaración continua en el bloque de la declaración for o while en el bloque de lenguaje imperativo.
Una declaración de "retorno" finaliza la ejecución de la función más interna y regresa a su llamador, o
finaliza el bloque de idioma imperativo más interno y regresa al bloque de idioma o función de nivel
superior.
Una declaración de "ruptura" finaliza la ejecución del bucle "for" o bucle " while" más interno .
Ejemplo:
yo = [Imperativo] {
a = 0;
while(true) // esto hará que el bucle while se ejecute indefinidamente {
a = a+1;
si (un == 10)
descanso; // cuando a es igual a 10, esta declaración sale del ciclo
} devuelve un; // un = 10
};
yo = [Imperativo] {
a = 0; l
= 1..100; para
(yo en l) {
a = yo;
si (a == 15)
romper;
Ejemplo:
yo = [Imperativo]
Machine Translated by Google
{
a = 0;
l = 1..10;
para (yo en l)
{
if(i%2 != 0) // salta todos los números impares
Continuar; // continuar con la siguiente iteración del ciclo, omitir el resto del cuerpo
a = a + yo;
Una instrucción "continuar" inicia la siguiente iteración del bucle "for" o bucle " while" más interno .
7.6. Si declaraciones
Las declaraciones "si" especifican la ejecución condicional de múltiples ramas en función del valor booleano de cada
expresión condicional. Las declaraciones "si" solo son válidas en el bloque de lenguaje imperativo.
IfStatement =
“if” “(” Expression “)” StatementBlock { “elseif” “(”
Expression “)” StatementBlock } [ “else” StatementBlock ]
Ejemplo:
x = 5;
si (x > 10) { y =
1;
} elseif (x > 5) { y =
2;
} elseif (x > 0) { y =
3;
} más
{ y = 4;
}
7.7. Bucles
En el código Imperative DesignScript, un programador tiene la opción de escribir código que itere manualmente sobre la
lista, extrayendo elementos individuales de la colección uno a la vez. Los bucles son construcciones de lenguaje para
repetir la ejecución sobre un bloque de código. El número de veces que se llama a un bucle se puede regir por la longitud
de la lista (bucle "for") donde se llama al bucle con cada elemento de la lista como entrada. El número de iteraciones de
un bucle también se puede determinar mediante una expresión booleana ("bucle while"), donde se llama al bucle hasta
que la expresión booleana devuelve falso. Los bucles se pueden utilizar para generar colecciones, buscar una solución o
llamar de forma repetitiva a un determinado bloque de código.
Machine Translated by Google
Las declaraciones "while" ejecutan repetidamente un bloque en un bucle hasta que la condición se vuelve falsa. Las
declaraciones "while" solo son válidas en el bloque de lenguaje imperativo. Un ciclo while puede ejecutarse infinitamente
si la condición no se evalúa como falsa , por lo que es importante tener una condición de terminación para salir del ciclo,
a menos que haya una declaración de interrupción explícita dentro del ciclo que obligue a la ejecución a salir del ciclo
while . .
Ejemplo:
suma =
0; x = 0;
mientras (x < 10)
{
suma = suma +
x; x = x + 1;
} // suma == 55
"for" itera todos los valores en la cláusula "in" y asigna el valor a la variable de bucle. La expresión en la cláusula "in"
debe devolver una lista; si es un singleton, es una evaluación de declaración única. Las declaraciones "for" solo son
válidas en el bloque de lenguaje imperativo. Al igual que las sentencias while , se puede salir de un bucle for utilizando
una sentencia break en el cuerpo de la sentencia for .
Ejemplo:
suma =
0; para (x en 1..10) {
suma = suma + x;
} // suma == 55
8. Bloques de idioma
DesignScript tiene dos paradigmas de lenguaje: asociativo e imperativo. Cada uno de estos idiomas está escrito
en sus respectivos bloques de idioma.
Machine Translated by Google
A diferencia de un bloque de idioma anidado, no hay declaración de retorno en el bloque de idioma asociativo de nivel superior.
Las declaraciones en el bloque de lenguaje asociativo predeterminado se ejecutan en el orden en que las declaraciones
dependen unas de otras. Esto significa que todas las dependencias de una instrucción se ejecutan antes que la propia
instrucción, independientemente del orden en que se produzcan las instrucciones en el bloque asociativo.
Las declaraciones en un bloque asociativo anidado se ejecutan secuencialmente hasta que una declaración de retorno devuelve un
valor; de lo contrario, el bloque de idioma devuelve nulo.
No es válido definir un bloque de idioma anidado dentro de un bloque anidado del mismo tipo.
Ejemplos:
x = 1;
// z = 3 z
= [Asociativo] {
y = 2;
devuelve x + y;
}
[Asociativo] {
Las diferencias clave entre el bloque de idioma asociativo y el bloque de idioma imperativo son: • La
actualización asociativa está deshabilitada en el bloque de idioma imperativo. • Las declaraciones
"if", "for" y "while" solo están disponibles en bloques de lenguaje imperativo.
Ejemplo:
x = 1;
si (x > 10)
{ devuelve 3;
} más si (x > 5)
{ devuelve 2;
} más
{ devuelve 1;
}
}
def suma(x)
{
// define un bloque de lenguaje imperativo dentro de una función, que está en un // bloque de lenguaje
asociativo global return [Imperative] {
s = 0;
para (i en 1..x) {
s = s + yo;
}
devoluciones;
}
}
[Asociativo] {
volver 42;
}
}
[Imperativo] {
}
}
se repetirá La
replicación zip predeterminada es la replicación zip más corta; de lo contrario, debe usar la guía de replicación
para especificar el enfoque más largo.
• Replicación cartesiana: equivale a bucle anidado en lenguaje imperativo. Por ejemplo, para los
argumentos de entrada x = [x1, x2, ..., xn] e y = [y1, y2, ..., yn], al llamar a la función f(x, y) con
replicación cartesiana y los índices cartesianos son [0, 1], lo que significa que la iteración sobre el
primer argumento es el primer ciclo, y la iteración sobre el segundo argumento es el ciclo anidado;
es equivalente a [f(x1, y1), f(x1, y2), ..., f(x1, yn), f(x2, y1), f(x2, y2), ..., f( x2, yn), ..., f(xn, y1), f(xn,
y2), ..., f(xn, yn)].
La guía de replicación se utiliza para especificar el orden de los índices de replicación cartesiana; la guía de replicación
inferior, el lazo exterior. Si dos guías de replicación tienen el mismo valor, se aplicará la replicación zip.
Guía de replicación = “<” número [“L”] “>” {“<” número [“L”] “>”}
Solo se permite un valor entero en la guía de replicación. El sufijo "L" indica si la replicación es una replicación zip, luego
use la estrategia de replicación zip más larga. El número de guía de replicación especifica el nivel anidado.
Por ejemplo, la guía de replicación xs<1><2> indica que el argumento debe ser al menos bidimensional y su nivel
anidado es 2; también podría expresarse mediante el siguiente pseudocódigo:
Machine Translated by Google
// xs<1><2>
para (ys en xs) {
para (y en ys) {
...
}
}
Ejemplo:
devuelve x + y;
}
x = [1, 2]; ys =
[3, 4]; zs = [5,
6, 7];
// la replicación zip más larga debe especificarse a través de la guía de replicación. // las guías de
aplicación deben tener el mismo valor; de lo contrario, // se aplicará la replicación cartesiana r3 =
add(xs<1L>, zs<1L>); // r3 = [6, 8, 9]
Además de la replicación para la llamada de función explícita, la guía de replicación y replicación también se puede aplicar
a las siguientes expresiones: 1. Operadores binarios como +, -, *, /, etc. Todos los operadores binarios en DesignScript se
pueden ver como una función que acepta dos parámetros, y el operador unario se puede ver como una función que
acepta un parámetro. Por lo tanto, la replicación se aplicará a la expresión “xs + ys” si “xs” e “ys” son listas.
2. Expresión de rango.
3. Expresión condicional en línea en forma de “xs ? ys : zs” donde “xs”, “ys” y “zs” son listas.
4. Indexación de matriz. Por ejemplo, xs[ys] donde ys es una lista. La replicación podría aplicarse a la matriz
indexación en ambos lados de la expresión de asignación. Tenga en cuenta que la replicación no se aplica a varios
índices.
Machine Translated by Google
5. Expresión de acceso a miembros. Por ejemplo, xs.foo(ys) donde xs e ys son listas. Replicación
La guía podría aplicarse a objetos y argumentos. Si xs es una lista, xs debería ser una lista homogénea, es decir,
todos los elementos en xs son del mismo tipo.
Tenga en cuenta que si el argumento es una lista irregular, el resultado de la replicación no está definido.
Formalmente, para una función "f(x1: t1, x2: t2, ..., xn: tn)" y argumentos de entrada "a1, a2, ..., an", la regla de envío de la
función es: 1. Obtener una lista de la función sobrecargada f() con el mismo número de parámetros. Estas funciones son
candidatos.
2. Si existen guías de replicación, se procesarán nivel por nivel. Por ejemplo, para la llamada de función f(as<1><1>,
bs, cs<1><2>, ds<2><1L>), existen dos niveles de guías de replicación.
una. Para cada nivel, ordene las guías de replicación en orden ascendente. Si la guía de replicación es inferior a
o igual a 0, se omitirá esta guía de replicación (es una guía de replicación stub).
i. Para cada guía de replicación, si aparece en varios argumentos, se aplica la replicación zip.
Por defecto, usando el cordón más corto. Si algún número de guía de replicación tiene el
sufijo "L", se aplica el lazado más largo. ii. De lo contrario, se aplica la replicación cartesiana.
iii. Repita el paso b hasta que se hayan procesado todas las guías de replicación.
4. Con base en esta lista de reducción, calcule una combinación de listas de reducción cuyos valores de elementos sean
menores o iguales que el valor de reducción correspondiente en la lista de reducción base. Para cada lista de
reducción [r1, r2, ..., rn], realice iterativamente el siguiente cálculo para generar repeticiones: a. Para cualquier ri >
0, ri = ri - 1. Si hay múltiples reducciones cuyos valores son mayores o iguales a 1, se aplica la replicación zip; de
lo contrario, se aplica la replicación cartesiana.
5. Combine las replicaciones generadas en los pasos 3 y 4, en función de los argumentos de entrada y la firma de las
funciones candidatas, elija la mejor función coincidente y la mejor estrategia de replicación. Durante el proceso, si
el tipo de parámetro y el tipo de argumento son diferentes, se calculará la puntuación de distancia de tipo.
10. Lista@Nivel
List@Level es una función de lista especial que devuelve una lista aplanada en un nivel específico. Si una entrada se
especifica como una lista dominante, la estructura de la salida será la misma que la estructura de la lista dominante.
Por ejemplo, para dos entradas xs (lista de rango 4) e ys (lista de rango 3), queremos llamar a la función f() con el
segundo nivel de xs e ys, donde xs es la lista dominante: +(xs@@L2 , ys@L2). La salida conserva la estructura de la lista de
xs , ya que es la lista dominante (representada por el símbolo doble '@'):
xs sí
ys@L2 devuelve:
Machine Translated by Google
[
[1, 2]
[3, 4]
[5, 6]
[7, 8]
[9, 10]
[11, 12]
]
xs@L2 devuelve:
[
[a, b]
[c, d]
[e, f]
[g, h]
[i, j]
]
Machine Translated by Google
virtual. Estos no están expuestos en la interfaz de usuario de Dynamo, pero aún se pueden invocar desde el bloque de código.
nodos:
• Cuenta:int(lista: var[]..[])
Devuelve el número de elementos de la lista especificada.
• Transponer:var[]..[](lista: var[]..[])
Intercambia filas y columnas en una lista de listas. Si hay algunas filas que son más cortas que otras, los valores nulos se
insertan como marcadores de posición en la lista de resultados de modo que siempre sea rectangular.
• __GC()
Forzar la recolección de basura.
Las siguientes funciones integradas se exponen al usuario final como heredadas de la clase FFI List:
12. Internos
que la actualización asociativa está deshabilitada en los nodos de bloque de código al no permitir la redefinición de
variables, sin embargo, el lenguaje en sí lo admite. La actualización asociativa se puede ver en acción escribiendo archivos
DesignScript y ejecutándolos.
La asociatividad es una característica de DesignScript que permite la propagación de un cambio de variable a todas las
declaraciones dependientes del programa. La propagación del cambio ocurre en tiempo de ejecución y es manejada por el mecanismo
de actualización de la máquina virtual DesignScript.
1: x = 1; 2:
y = x; 3: x
= 3;
En la línea 2, “y” depende de “x”, o “y” depende de “x”; luego, en la línea 3, el cambio de "x" actualizará "y" mediante la reejecución
de la instrucción de asignación correspondiente que establece la asociatividad.
Por otro lado, si el código está en bloque de lenguaje imperativo, el cambio de "x" no actualizará "y", al igual que otros lenguajes de
programación.
• Propiedades 4.
Las entidades de las que se puede depender son •
Variables
• Propiedades
• Funciones
Es importante señalar que las entidades asignadas y las entidades de las que se depende deben definirse en el mismo
ámbito. Ver ámbito de asociatividad.
1: x = 1; 2:
y = 2; 3: z
= foo(x, y); 4: x = 3;
5: y = 4; 6: z = 0; 7:
x = 5;
En la línea 3, la asignación establece la asociatividad entre “z” y “foo”, “x” e “y”, por lo que “z” dependerá de “foo”, “x” e “y”.
Después de actualizar “x” a 3, la línea 3 se volverá a ejecutar para actualizar “z”; después de actualizar "y" a 4 en la línea 5, la
línea 3 se volverá a ejecutar.
En la línea 6, la redefinición de “z” elimina la asociatividad previamente establecida. Ahora "z" ya no depende de otras entidades,
por lo que la siguiente actualización de "x" en la línea 7 no incurrirá en un nuevo cálculo de "z".
La declaración de asignación en el bloque de lenguaje imperativo cambia solo las variables/propiedades a las que están asignadas
y no tiene una actualización implícita.
[Imperativo] {
Machine Translated by Google
1: x = 1; 2: y
= x; 3: x = 3; }
El código se ejecuta línea por línea, no se volverá a realizar ningún cálculo en el bloque de idioma imperativo. Después de la
ejecución, "x" es 3 e "y" es 1.
12.1.3. dependientes
Un dependiente puede ser una variable o una propiedad. El siguiente código muestra el último caso:
clase Foo {
X;
}
f = Foo(); m =
21;
metro = 42;
r = fx; // r es 42
Después de que "m" se actualice a 42, la declaración de asignación "fx = m" se volverá a ejecutar para actualizar la propiedad "x".
12.1.4.1. Variables
El cambio de variable desencadenará actualizaciones de sus dependientes. La variable podría aparecer en:
• Expresión •
Parámetros: en forma de “x = f(y, z)”, donde “x” depende de “f()” y de las variables “y” y
“z”.
• Indexación de listas: en forma de “x = y[z]”, donde “x” depende tanto de las variables “y” como de la variable indexadora
de matrices “z”.
Hay un caso especial para la autorredefinición, es decir, una variable depende de sí misma. Por ejemplo, “a = a + 1”.
Este tipo de autorredefinición no eliminará la asociatividad previamente establecida entre “a” y otras variables. Además, el cambio
de "a" solo actualizará sus dependientes, no "a" en sí. El siguiente ejemplo ilustra este caso:
Machine Translated by Google
1: x = 1; 2:
y = 2; 3: x
= x + y; 4: z = x
+ y; 5: x = x + 1;
2. “y” se establece en
2. 3. “x” se cambia a “x + y”. Entonces "x" depende de "y", "x" es 3 ahora. 4. “z” se
establece en “x + y”. Entonces "z" depende de "x" e "y", "z" es 5 ahora. 5. "x" se incrementa
en 1. Se activará la actualización de "z" , "z" es 6 ahora.
También está bien que la variable aparezca en la lista de parámetros de la función, tal como muestra el ejemplo en el
establecimiento de la asociatividad .
12.1.4.2. Función
En forma de:
x = f(...);
La asignación establece asociatividad entre “x” y la función “f()”. Cualquier actualización del cuerpo de la función de cualquier "f ()"
sobrecargada provocará la reejecución de esta declaración. Tenga en cuenta que esta función solo está disponible cuando Live Runner
está habilitado (que solo está disponible en el entorno de programación visual).
12.1.4.3. Propiedades
En forma de:
r = xyz;
La asignación establece asociatividad entre “r” y variable “x” y propiedades “y” y “z”. Cualquier actualización de "x", "y" y "z" actualizará
"r".
Ejemplo:
clase Foo {
X;
constructor Foo(_x) {
x = _x;
}
}
Machine Translated by Google
barra de clase
{
foo;
constructor Barra(_x) {
Foo = Foo(_x);
}
}
b = Barra(0); t
= b.foo.x;
Cada actualización en las últimas tres declaraciones volverá a ejecutar la declaración "t = b.foo.x" para actualizar el valor de "t".
1. El dependiente se define en el ámbito superior y depende de las variables definidas en el mismo ámbito,
pero la asociatividad se establece en la función. Por ejemplo, en el código siguiente, "x" e "y" , ambos definidos en el
bloque de lenguaje asociativo global. La ejecución de "foo()" ejecutará la línea 5 para establecer la asociatividad entre "x"
e "y". El comportamiento esperado de este tipo de asociatividad no está definido, por lo tanto, actualizar "y" a 3 no
necesariamente actualizará "x" ya que la máquina virtual DesignScript no admite ejecutar solo la línea 5 sin ejecutar toda
la función "foo()".
1: x = 1; 2:
y = 2; 3:
def foo() 4: { 5:
x = y;
6: devolver nulo;
7: }
8: 9:
foo(); 10: y
= 3; // la actualización de "x" no está definida
2. El dependiente se define en el ámbito superior y depende de variables definidas en el mismo ámbito, pero la asociatividad
se establece en bloque de lenguaje anidado. Por ejemplo, en el siguiente código, "x" y
Machine Translated by Google
"y" ambos definidos en el bloque de lenguaje asociativo global. La ejecución del lenguaje imperativo anidado
establecerá la asociatividad entre "x" e "y" en la línea 5, pero el comportamiento esperado de este tipo de asociatividad
tampoco está definido.
1: x = 1; 2:
y = 2;
3: [Imperativo] 4: { 5:
x = y;
6: devolver nulo;
7: }
8: y = 3; // la actualización de "x" no está definida
3. El dependiente se define en el ámbito superior pero depende de las variables definidas en la función. Para
ejemplo, “x” depende de la variable local “y” en “foo()”.
1: x = 1; 2:
def foo() 3: { 4:
y = 2; x
5: = y;
6: devolver nulo;
7: }
8: foo(); 9:
y = 3;
4. El dependiente se define en el ámbito superior pero depende de las variables definidas en el bloque de idioma anidado. Por
ejemplo, "x" depende de la variable local "y" en el bloque de lenguaje imperativo anidado.
1: x = 1;
2: [Imperativo] 3: { 4:
y = 2; x
5: = y;
6: devolver nulo;
7: }
12.2. Clases
Nota: Las clases solo se pueden declarar en archivos de script DesignScript o archivos que tengan una extensión .DS. Las
declaraciones de clase no están permitidas en los nodos de bloque de código en Dynamo. Los archivos de DS se pueden importar a
una sesión de Dynamo para consumirlos como nodos.
Machine Translated by Google
ClassDeclaration =
identificador de "clase" [identificador de "extensión"]
“{“ [Declaración de miembro de clase] “}”
ClasMemberDeclaration =
Declaración de constructor
| Declaración de miembro
Declaración de constructor =
identificador de “constructor” Lista de parámetros
[“:” “base” “(“ ArgumentList “)”]
DeclaraciónBloque
Declaración de miembro =
[Modificador de acceso] [estática] (Declaración de función | Declaración de variable “;”)
12.2.2. Herencia
DesignScript solo admite la herencia única. Es decir, solo se permite una clase base.
Ejemplo:
clase Punto2D {
...
}
...
}
12.2.3. Constructores
Aunque no es forzado, pero se sugiere que el nombre del constructor comience con “Por…” para indicar
cómo crear el objeto. Por ejemplo, el constructor de la creación de un Punto puede ser “ByCoordinates()”.
Si la clase hereda de la otra clase, es posible llamar al constructor de la clase base llamando a
"base(...)".
Para crear una instancia de clase, use la declaración de creación de objetos "ClassName.ConstructorName (...)". Si el
nombre del constructor es el mismo que el nombre de la clase, o una clase no tiene constructor (en este caso, un
Machine Translated by Google
Ejemplo:
clase Punto2D {
constructor PorCoordenadas(x, y) {
...
}
}
...
}
constructor Punto3D() {
...
}
}
12.2.4. Propiedades
Las variables definidas en clase son propiedades. La inicialización de propiedades podría estar en el constructor o en la
definición.
Para distinguir las propiedades de otros tipos de variables, se podría usar la expresión de acceso
de miembros “this.property_name” o “'base.property_name” para indicar que “property_name” es una propiedad de la
clase o una propiedad de la clase base.
clase Punto2D {
constructor PorCoordenadas(x, y)
Machine Translated by Google
{
esto.x = x;
esto.y = y;
}
}
z = 0;
esto.z = z;
}
constructor Punto3D() {
= 1; // es propiedad
// es
“y” propiedad
de la clase“x”
base
de la
z =clase
1; base x = 1; base.y
}
}
// x == 1 x =
p1.x;
• Se puede acceder a los miembros públicos desde cualquier lugar dentro y fuera de la clase. •
Solo se puede acceder a los miembros protegidos en la clase o en la clase derivada. • Solo se
puede acceder a los miembros privados en la clase.
Ejemplo:
Machine Translated by Google
base de clase
{
propiedad
privada1; prop2
protegida; público prop3;
definición privada
foo1() {...}
() {
}
}
b = Base();
• No es válido si una propiedad estática tiene el mismo nombre que una propiedad no estática o un miembro estático
tiene la misma firma que una función miembro no estática. • No es necesario
tener "ClassName". prefijo al llamar a miembros estáticos en la clase.
clase Foo {
X;
Y estático;
def foo() { }
// error: foo() se ha definido como una función miembro no estática static def foo()
{}
def qux() {
}
}
f = Foo();
Ejemplo:
clase desechable {
def _Dispose() {
Bandera = verdadero;
}
}
[Imperativo] {
d = Desechable();
__GC(); //
"d" será basura recolectada
}
// Desechable.Bandera es verdadera
r = Desechable.Bandera;