elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


Tema destacado: AIO elhacker.NET 2021 Compilación herramientas análisis y desinfección malware


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  En muchos lenguajes, tempArray = array ¿es una referencia y les parece bien?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: En muchos lenguajes, tempArray = array ¿es una referencia y les parece bien?  (Leído 564 veces)
Tachikomaia


Desconectado Desconectado

Mensajes: 1.502


Hackentifiko!


Ver Perfil
En muchos lenguajes, tempArray = array ¿es una referencia y les parece bien?
« en: 12 Enero 2025, 21:51 pm »

A esto:
https://foro.elhacker.net/programacion_general/iquestque_metodo_es_recomendado_para_ordenar_al_azar_un_array-t522940.0.html
...quería agregarle eficientemente que el nuevo array pudiera tener menos elementos que el original. Como no se me ocurrió bien cómo, consulté a GPT:

En Macromedia Flash 5 tengo un array de 3 elementos y quiero que se genere otro array con 2 de esos elementos al azar, y ordenados al azar ¿cómo?

Citar
En **Macromedia Flash 5**, puedes usar `ActionScript` para lograr lo que necesitas: generar un nuevo array con dos elementos seleccionados al azar del array original, y luego ordenarlos aleatoriamente. Aquí tienes un ejemplo de código que hace exactamente eso:

```actionscript
// Array original con 3 elementos
var originalArray = ["Elemento1", "Elemento2", "Elemento3"];

// Función para seleccionar 2 elementos al azar del array original
function getRandomElements(array) {
    // Copiar el array original para no modificarlo
    var tempArray = array.slice(0);
    var randomArray = [];
    
    // Seleccionar 2 elementos al azar
    for (var i = 0; i < 2; i++) {
        var randomIndex = Math.floor(Math.random() * tempArray.length);
        randomArray.push(tempArray[randomIndex]);
        // Remover el elemento seleccionado para evitar duplicados
        tempArray.splice(randomIndex, 1);
    }
    
    // Mezclar los elementos seleccionados
    randomArray.sort(function() {
        return Math.random() - 0.5;
    });
    
    return randomArray;
}

// Generar el nuevo array con 2 elementos al azar y ordenados al azar
var newArray = getRandomElements(originalArray);

// Mostrar el resultado
trace("Array original: " + originalArray);
trace("Nuevo array: " + newArray);
```

### Explicación del código:

1. **Copia del array original**:
   - Usamos `slice(0)` para crear una copia del array original, de modo que no lo modifiquemos al eliminar elementos.

2. **Selección aleatoria**:
   - En el loop, se seleccionan dos elementos al azar usando `Math.random()` y se eliminan del array temporal (`tempArray`) con `splice()`, para evitar duplicados.

3. **Orden aleatorio**:
   - Usamos `sort()` con una función de comparación que devuelve un valor aleatorio para mezclar los elementos seleccionados.

4. **Resultado**:
   - El nuevo array (`newArray`) contiene dos elementos seleccionados al azar del array original, y están ordenados de manera aleatoria.

### Ejemplo de salida:

Si el array original es `["Elemento1", "Elemento2", "Elemento3"]`, la salida podría ser algo como:

```
Array original: Elemento1,Elemento2,Elemento3
Nuevo array: Elemento2,Elemento1
```

Cada vez que ejecutes el código, la selección y el orden serán diferentes.

¿por qué pones
var tempArray = array.slice(0);
en vez de
tempArray = array;
?

Citar
La razón por la que usé:

```actionscript
var tempArray = array.slice(0);
```

en lugar de:

```actionscript
tempArray = array;
```

es para **crear una copia del array original**, en lugar de simplemente referenciarlo.

### Diferencia entre copiar y referenciar un array:

- **`tempArray = array;`**  
  Esto no crea un nuevo array. En lugar de ello, `tempArray` apunta al mismo espacio de memoria que el array original (`array`). Si modificas `tempArray` (como eliminar elementos con `splice()`), también estarás modificando el array original, porque ambos comparten el mismo contenido.

- **`tempArray = array.slice(0);`**  
  Esto crea una **copia del array original**. Cualquier cambio que hagas en `tempArray` no afectará al array original, ya que ahora son dos arrays independientes.

### ¿Por qué es importante en este caso?

En el código, usamos `splice()` para eliminar elementos del array temporal (`tempArray`) mientras seleccionamos elementos aleatorios. Si no hacemos una copia (usando `slice()`), también estaríamos eliminando elementos del array original, lo cual probablemente no sea lo que queremos.

### Ejemplo práctico:

Supongamos que tienes este código:

```actionscript
var originalArray = ["Elemento1", "Elemento2", "Elemento3"];
var tempArray = originalArray;

// Modificar tempArray
tempArray.splice(0, 1);

// Imprimir ambos arrays
trace("originalArray: " + originalArray);
trace("tempArray: " + tempArray);
```

**Salida:**

```
originalArray: Elemento2,Elemento3
tempArray: Elemento2,Elemento3
```

Como ves, al modificar `tempArray`, también se modifica `originalArray`, porque ambos apuntan al mismo array.

Ahora, usando `slice(0)`:

```actionscript
var originalArray = ["Elemento1", "Elemento2", "Elemento3"];
var tempArray = originalArray.slice(0);

// Modificar tempArray
tempArray.splice(0, 1);

// Imprimir ambos arrays
trace("originalArray: " + originalArray);
trace("tempArray: " + tempArray);
```

**Salida:**

```
originalArray: Elemento1,Elemento2,Elemento3
tempArray: Elemento2,Elemento3
```

Aquí, `originalArray` permanece intacto, porque `tempArray` es una copia independiente.

### Conclusión:

Usar `slice(0)` asegura que puedas trabajar con un array temporal sin modificar el array original. Esto es crucial cuando necesitas preservar el estado del array original para otros usos o simplemente para evitar efectos secundarios no deseados.

Poner un nombre, luego = y luego un valor, es crear una variable cuyo nombre es el indicado en nombre y su valor es indicado luego del signo =, no es una referencia ¿o estoy equivocado?

Citar
Estás en lo correcto en términos generales: cuando haces algo como:

```actionscript
var nombre = valor;
```

estás creando una variable llamada `nombre` y asignándole el valor de `valor`. Sin embargo, **el comportamiento de la variable depende del tipo de dato que estés asignando**. En ActionScript (y en muchos lenguajes de programación), los tipos de datos se dividen principalmente en dos categorías:

1. **Tipos primitivos** (números, cadenas, booleanos, etc.).
2. **Tipos complejos o de referencia** (objetos, arrays, etc.).

La diferencia clave radica en cómo se asignan y manejan los valores en memoria.

---

### Tipos primitivos: Copia del valor

Cuando asignas un tipo primitivo a una variable, se copia su valor directamente en la nueva variable. Por ejemplo:

```actionscript
var a = 5;
var b = a;
b = 10;

trace(a); // 5
trace(b); // 10
```

Aquí, `a` y `b` son independientes, porque el número `5` (un tipo primitivo) se copió en `b`. Cambiar `b` no afecta a `a`.

---

### Tipos complejos (como arrays): Referencia en memoria

Cuando trabajas con tipos complejos, como arrays u objetos, lo que realmente estás asignando no es el "valor" en sí, sino una **referencia en memoria** al lugar donde se almacenan esos datos. Esto significa que si usas el operador `=` para asignar un array a otra variable, ambas variables apuntarán al mismo array en memoria. Por ejemplo:

```actionscript
var originalArray = [1, 2, 3];
var otherArray = originalArray;

otherArray.push(4);

trace(originalArray); // [1, 2, 3, 4]
trace(otherArray);    // [1, 2, 3, 4]
```

Aquí, tanto `originalArray` como `otherArray` apuntan al mismo array en memoria. Al modificar `otherArray`, también estás modificando `originalArray`.

Si quieres evitar este comportamiento y trabajar con una copia independiente del array, necesitas crear una copia explícita, como con el método `slice()`:

```actionscript
var originalArray = [1, 2, 3];
var otherArray = originalArray.slice(0);

otherArray.push(4);

trace(originalArray); // [1, 2, 3]
trace(otherArray);    // [1, 2, 3, 4]
```

Ahora, `originalArray` y `otherArray` son arrays completamente separados, y los cambios en uno no afectan al otro.

---

### Conclusión

Cuando haces:

```actionscript
tempArray = array;
```

no estás creando un nuevo array. Estás haciendo que `tempArray` apunte al mismo array en memoria que `array`. Por eso, cualquier cambio que hagas en `tempArray` también se verá reflejado en `array`.

Si quisieras que `tempArray` sea una copia independiente del contenido de `array` (sin afectar al original), necesitas usar algo como:

```actionscript
tempArray = array.slice(0);
```

Esto crea un nuevo array con el mismo contenido, pero almacenado en un espacio de memoria diferente.

En resumen: la diferencia entre **valor** y **referencia** es lo que causa este comportamiento.

¿Por qué lo hicieron así?

Citar
Implementar arrays y objetos como **tipos por referencia** en lenguajes como ActionScript (y otros lenguajes como javascript, Python, etc.) no es algo arbitrario, tiene razones prácticas y de diseño. Aquí te explico por qué **los arrays y objetos funcionan por referencia** y no como copias directas:

---

## 1. **Eficiencia en memoria y rendimiento**
Cuando trabajas con tipos complejos como arrays u objetos, estos pueden contener grandes cantidades de información. Si cada vez que los asignaras a una nueva variable se hiciera una copia completa de los datos, esto consumiría mucha memoria y sería muy lento.

Por ejemplo, considera este caso:

```actionscript
var arrayGrande = [1, 2, 3, ..., 100000]; // Un array con 100,000 elementos
var copia = arrayGrande; // ¿Qué pasaría si fuera una copia completa?
```

Si el lenguaje copiara todo el array al asignarlo, el programa tendría que:

1. Reservar **el doble** de espacio en memoria para almacenar los mismos datos.
2. Copiar cada uno de los 100,000 elementos al nuevo array.

Esto haría que las operaciones de asignación fueran lentas y que el uso de memoria se disparara rápidamente en aplicaciones que manejan muchos datos.

**Por referencia**, en cambio, el lenguaje simplemente crea un "puntero" o "referencia" al espacio de memoria donde ya está almacenado el array. Esto es mucho más rápido y eficiente porque no duplica los datos, sino que solo comparte la referencia.

---

## 2. **Facilita la mutabilidad**
Cuando trabajas con objetos y arrays, muchas veces necesitas que todos los cambios se reflejen en el mismo lugar. Si los arrays fueran siempre copiados al asignarlos, sería complicado coordinar los cambios entre diferentes partes de tu código.

Por ejemplo:

```actionscript
var config = { ancho: 800, alto: 600 };
var referencia = config;

referencia.ancho = 1024;

trace(config.ancho); // 1024
```

Aquí, tanto `config` como `referencia` apuntan al mismo objeto. Si cambias un valor en `referencia`, también se refleja en `config`, porque ambos son referencias al mismo objeto. Esto facilita que múltiples variables o funciones trabajen con los mismos datos sin necesidad de copiar y sincronizar los cambios manualmente.

Si los objetos fueran copiados automáticamente, el cambio en `referencia` no afectaría a `config`, y tendrías que buscar formas más complicadas de mantenerlos sincronizados.

---

## 3. **Es coherente con el diseño de programación orientada a objetos**
Los lenguajes como ActionScript están diseñados para manejar objetos de manera flexible. En este paradigma, los objetos y arrays suelen comportarse como entidades compartidas, **en lugar de duplicarse automáticamente**. Esto es clave para trabajar con estructuras de datos dinámicas, como listas enlazadas, árboles, o gráficos, donde las relaciones entre los elementos son importantes.

Por ejemplo:

```actionscript
var nodo1 = { valor: 1, siguiente: null };
var nodo2 = { valor: 2, siguiente: nodo1 };

trace(nodo2.siguiente.valor); // 1
```

Este tipo de estructuras serían mucho más difíciles de implementar si cada asignación hiciera copias completas de los datos.

---

## 4. **Consistencia con otros lenguajes**
ActionScript heredó muchas de sus características de javascript (que, a su vez, está inspirado en otros lenguajes como Java). En todos estos lenguajes, los objetos y arrays funcionan por referencia. Esto hace que el comportamiento sea predecible y **consistente con el estándar de la industria**, lo que facilita a los programadores aprender y trabajar con lenguajes similares.

---

## ¿Por qué no hacerlo todo por valor?
Si trabajar por referencia es tan eficiente, podrías preguntarte por qué no todos los tipos de datos funcionan así. La razón es que **los tipos primitivos (como números, cadenas y booleanos)** son mucho más simples y pequeños en términos de tamaño en memoria. Duplicarlos no es costoso y, en la mayoría de los casos, es más útil que sean independientes.

Por ejemplo:

```actionscript
var a = 5;
var b = a;
b = 10;

trace(a); // Todavía es 5
trace(b); // Es 10
```

En este caso, trabajar **por valor** tiene sentido porque los números son pequeñas cantidades de datos y se espera que sean independientes.

---

## Conclusión
Los arrays y objetos funcionan por referencia porque:

1. **Es más eficiente** en términos de memoria y rendimiento.
2. **Facilita la mutabilidad**, permitiendo que los cambios se reflejen automáticamente en todas las referencias.
3. **Es coherente** con el diseño de programación orientada a objetos.
4. **Sigue un estándar** que es consistente con otros lenguajes.

Aunque este comportamiento puede parecer confuso al principio, con el tiempo te darás cuenta de que es una decisión lógica y práctica para manejar datos complejos. Si necesitas una copia independiente, siempre puedes usar métodos como `slice()` o técnicas específicas para clonar objetos y arrays.

No le veo sentido, si quiero crear una copia debería poder hacerlo normalmente no con "slice", si consume mucho entonces el programador debería saberlo y no usarlo salvo que sea útil ¿por qué limitarnos?

Claro que no entendí todos los motivos que dice ahí, que una variable tenga 2 nombres puede ser útil pero... Si fuese así, debería poder hacerse con variables simples, y sobretodo debería poder hacerse de otro modo. Que una misma expresión, tan básica, haga cosas distintas según el tipo de variable parece absurdo.

¿Qué opinan?

Edit: Sabía que había excepciones a eso, tenemos por ejemplo que Número+Número es una suma pero si alguno de esos números es cadena entonces el + es concatenar. Pero vamos, no es lo mismo el + que el =. El = es sagrado xP

Edit2: Es como si al copiar un archivo en Windows, este en vez de eso copiara un acceso directo. Joder, si quiero una copia porque voy a modificar una, dejame copiar tranquilo  >:(


« Última modificación: 12 Enero 2025, 22:07 pm por Tachikomaia » En línea

EdePC
Moderador Global
***
Desconectado Desconectado

Mensajes: 2.198



Ver Perfil
Re: En muchos lenguajes, tempArray = array ¿es una referencia y les parece bien?
« Respuesta #1 en: 13 Enero 2025, 01:34 am »

En lenguajes clásicos donde prima la velocidad y menor consumo de recursos posibles es común encontrar esas peculiaridades, recuerda que antes no había tanto CPU y Ram como ahora, C por ejemplo usa los punteros para llevar esa eficiencia y tratar adecuadamente a las variables por su valor o por su referencia. En lenguajes más modernos y de mayor nivel como por ejemplo .Net ya existen formas de pasar variables por valor y por referencia a las funciones (donde creo yo es bastante importante), si mal no recuerdo también están en VBScript aunque igualmente para funciones.

En las páginas 62 y 63 del pdf de ayuda de ActionScript 5: Consulta de ActionScript, justamente explica con ejemplos lo mismo que te explicó ChatGPT sobre los datos primitivos y complejos (Arrays y Objetos).

Al menos yo entiendo que buscas eficiencia, y mejor aún si es fácil de entender, otra alternativa más simple es generar un número y luego otro, pero si este último es igual al primero generar otro hasta obtener uno distinto, es más simple, pero obviamente si van a ser más de dos números aleatorios ya pierde eficiencia y es mejor pensar en otra cosa.

Y la cosa es así: En javascript clásico y por ende en ActionScript solo los datos primitivos (String, Número y Booleano) se pasan siempre por valor, todos los demás se pasan por referencia.

Citar
Es como si al copiar un archivo en Windows, este en vez de eso copiara un acceso directo. Joder, si quiero una copia porque voy a modificar una, dejame copiar tranquilo  >:(

Desde Windows 7 y quizá desde Windows Vista, aparte de los accesos directos hay enlaces simbólicos que más o menos trabajan de esa forma, "por referencia", la razón es sencilla, si tienes un archivo o carpeta repetida por todos lados (típico en varios juegos o proyectos) para ahorrar espacio puedes crear un enlace simbólico y que solo exista un archivo/carpeta original pero muchas copias de tamaño ínfimo porque son como accesos directos pero a los ojos del sistema y demás programas es un archivo o carpeta totalmente normal



En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.890



Ver Perfil
Re: En muchos lenguajes, tempArray = array ¿es una referencia y les parece bien?
« Respuesta #2 en: Ayer a las 13:24 »

TL/DR

Edit2: Es como si al copiar un archivo en Windows, este en vez de eso copiara un acceso directo. Joder, si quiero una copia porque voy a modificar una, dejame copiar tranquilo  >:(

Sin pretenderlo has descrito una peculiaridad muy fastidiosa de Windows que sucede con ciertos archivos executables. Si arrastras el archivo *.exe a otra ubicación, en vez de moverse o copiarse el archivo, se crea un acceso directo (*.lnk). El sistema no te avisa de este comportamiento al realizar la operación de arrastrar y soltar (mover/copiar), así que si no estás prestando atención y acto seguido borras permanentemente el archivo original pensando que se ha copiado el archivo real, pierdes el original y es un fastidio. Para solucionarlo basta con arrastrar el archivo manteniendo apretado el botón derecho del mouse, y al soltarlo seleccionar la opción de mover o copiar,o en su defecto CTRL+X|C y CTRL+V.

Esto he notado que sucede generalmente con algunos (pocos) archivos executables asociados a instalaciones, y supongo que será por como estos motores de instalación configuran ciertas claves en el registro que podrían alterar el comportamiento por defecto al arrastrar y soltar ese archivo .exe instalado.
No recuerdo ahora mismo si he visto que ocurriese esto con algún archivo protegido del sistema y que además no fuese un *.exe, sinceramente no lo recuerdo, pero creo que en mi caso no. Además, es que yo utilizo la cuenta "oculta" e integrada 'Administrador', y con UAC desactivado para olvidarme por completo de que para otras personas existen ciertas limitaciones a la hora de interactuar con archivos del sistema ...entre otras cosas xD.

Habría que informase en profundidad sobre el tema para entender mejor por que sucede esto.

Saludos.
« Última modificación: Ayer a las 13:28 por Eleкtro » En línea



Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Iría bien una hoja de referencia de las instrucciones de x86
Ingeniería Inversa
Bres 3 4,035 Último mensaje 3 Julio 2003, 08:45 am
por mlock
Te da la cabeza para aprender muchos lenguajes? « 1 2 3 »
Foro Libre
Edu 29 12,490 Último mensaje 22 Noviembre 2010, 22:03 pm
por Uxio
Array de muchos vectores
Java
DavidCC4 1 1,981 Último mensaje 16 Abril 2014, 00:17 am
por ivancea96
Pasar array dinamico por referencia
Programación C/C++
n-utz 2 3,974 Último mensaje 20 Noviembre 2016, 02:31 am
por Drewermerc
Máster en Desarrollo - de Cero a Avanzado. Muchos lenguajes
Tutoriales - Documentación
r32 0 3,231 Último mensaje 5 Diciembre 2020, 04:54 am
por r32
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines