¿Existe un lenguaje en el que las colecciones se puedan usar como objetos sin alterar el comportamiento?

7

¿Hay un lenguaje en el que colecciones se puedan usar como objetos sin alterar el comportamiento?

Como ejemplo, primero, imagina que esas funciones funcionan:

function capitalize(str) 
    //suppose this *modifies* a string object capitalizing it
function greet(person):
    print("Hello, " + person)

capitalize("pedro")
>> "Pedro"

greet("Pedro")
>> "Hello, Pedro"

Ahora, supongamos que definimos una colección estándar con algunas cadenas:

people = ["ed","steve","john"]

Entonces, esto llamará a Upper () en cada objeto en esa lista

people.toUpper() 
>> ["Ed","Steve","John"]

Y esto llamará saludo una vez para CADA gente en la lista, en lugar de enviar la lista como argumento

greet(people)
>> "Hello, Ed"
>> "Hello, Steve"
>> "Hello, John"
    
pregunta MaiaVictor 03.06.2012 - 23:33

3 respuestas

21

Sí, hay tales idiomas. Muchos de ellos.

De hecho, esta función es prácticamente la definición de un array language o vector language . Los ejemplos de lenguajes vectoriales y matriciales incluyen, entre otros, la familia de lenguajes APL con sus sucesores, derivados y primos (p. Ej., APL, J, K) y prácticamente todos los lenguajes matemáticos y estadísticos, como Mathematica, MATLAB, Octave, R, y S.

Fortran 90 y Ada también tienen esta característica, al igual que Fortress.

Curiosamente, muchas CPU modernas también admiten la programación vectorial, por ejemplo, La arquitectura x86 con MMX, SSE, SSE2, SSE3 (Intel) y 3DNow! Conjuntos de instrucciones (AMD), las arquitecturas POWER y PowerPC con los conjuntos de instrucciones VMX y AltiVec, Sparc, MIPS, incluso ARM.

El lenguaje de Microsoft Research tiene el concepto de streams (aproximadamente similar a IEnumerable ). Las transmisiones funcionan casi exactamente como las describe. Aquí hay un ejemplo de la documentación de Cω (énfasis mío):

  

Una función de programación clave de Cω es el acceso generalizado a los miembros: el operador "punto" familiar es ahora mucho más poderoso. Por lo tanto, si el receptor es un flujo, entonces el acceso de los miembros se asigna sobre los elementos , por ejemplo. zones.ToString() asigna implícitamente la llamada al método sobre los elementos del flujo zones y devuelve un valor del tipo string* . Esta característica reduce significativamente la carga del programador.

Una propiedad muy interesante de este tipo de programación es que no solo le permite pensar semánticamente "aplicar una operación a todos los elementos a la vez", sino que también permite al implementador del lenguaje implementarlo mediante literalmente aplicando una operación a todos los elementos a la vez , IOW en paralelo .

    
respondido por el Jörg W Mittag 04.06.2012 - 05:42
1

Puedes obtener una semántica muy similar a la que estás pidiendo en casi todos los idiomas usando el patrón compuesto.

Dado que tienes algún tipo similar a este:

// pseudocode
class CustomString
{
    CustomString Composite;
    string Value;
}

... y un método Greet como este:

// pseudocode
public string Greet(CustomString cs)
{
    string ret;
    if (cs!= null)
        ret += "Hello " + cs.Value + newline;

    if (cs.Composite != null)
        ret += Greet(cs.Composite);
}

... puedes hacer llamadas como esta:

writeln(Greet(new CustomString("snorfys")))
>> Hello snorfys

cs = new CustomString("snorfys") { Composite = new CustomString("Dokkat") }
writeln(Greet(cs))
>> Hello snorfys
>> Hello Dokkat

Si trabajas mucho con árboles, la programación de esta manera se siente rápidamente (es decir, que cada nodo de árbol es, y se puede tratar, un subárbol).

    
respondido por el Steven Evers 04.06.2012 - 06:09
1

En C #, por ejemplo, hay extensiones (agregue la funcionalidad a la colección - debajo de ella aún sería un bucle, pero nada visible) y Linq - ejemplo:

public static IEnumerble<string> Capitalize(this IEnumerable<string> collection)
{
   var List<string> rtn = new List<string>(collection.Count());
   foreach (var item in collection) 
   {
      var ci = Thread.CurrentThread.CurrentCulture; 
      var textInfo = ci.TextInfo; 

      rtn.Add(textInfo.ToTitleCase(item)); 
   }
   return rtn;
}

[Nota: entregué esto con clave, así que tal vez algunos errores tipográficos]

alternativamente, ...

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{  
   source.ThrowIfNull("source");     
   action.ThrowIfNull("action");    
   foreach (T element in source)    
   {         
        action(element);     
   } 
} 

con una función para capitalizar

public static string Capitalize(this string str)
{
    var ci = Thread.CurrentThread.CurrentCulture; 
    var textInfo = ci.TextInfo; 

    return textInfo.ToTitleCase(str); 
 }

y luego

myColl.ForEach(x => x.Capitalize()); 

La diferencia es que la segunda le permite pasar cualquier función y para cualquier tipo de colección.

myCollection.Where(employee => emplyee.Age > 50).ForEach(employee => employee.Fire());

también funciona (de una manera despiadada: D)

    
respondido por el Wolf5370 04.06.2012 - 13:43

Lea otras preguntas en las etiquetas