Обновить
38
0

Пользователь

Отправить сообщение

REST - не фреймворк. То есть сравнивается набор правил с фреймворком.

Про сериализацию - вообще молчу, это прям какая-то магия для меня - передача данных по сети без сериализации. Если хотите сказать, что этим вопросом занимается сгенерированный protobuf код вместо разработчика, то так и надо говорить.

С каких пор JSON стал прибит гвоздями к REST? Что мне мешает использовать XML, YAML, да даже тот же protobuf или, вовсе, свой собственный формат? Про то, что JSON ещё как сжимается выше уже упомянули.

Как видим на схеме, у клиента и сервера есть дополнительный уровень в общении — клиентская и серверная заглушки.

А где схема-то?

Про балансировку и остальное уже сказали до меня.

Если сравнивать с QuarkXpress, то тогда стоит учитывать и LibreOffice с ценою (без поддержки) ₽0. Но тут же проблема в том, что все вокруг сидят именно на MS.

− все еще нельзя жить без gc. Хотя вроде wasm направление помаленьку продавливает этот вопрос

А можете дать какие-нибудь ссылки на информацию про реализацию Go без GC, а то ничего, кроме пары предложений а issue github и форумах, не удалось.

Всё-таки threads. fibers - немного иное

Таки горутины ближе к нитям, так как сопрограммы, и уж точно не являются потоками.

Без них прям никак?

Ну без них примерно как в C. Но авторы языка зачем-то добавили интерфейсы и композицию, только они не решают всех задач, в частности, не позволяют писать библиотеки с обобщёнными алгоритмами, для которых дженерики как раз и нужны, поэтому в том же C есть, abs и fabs. При том, что по факту они там (в Go) есть, но только те, что дали разработчики языка.

Как вы думаете, почему один из создателей ЯП Go, имевший ранее опыт в создании другого довольно успешного ЯП, пошёл на такой шаг? Ведь Си довольно быстрый и в нём нет никакого gc, правда могут быть серьёзные проблемы, когда прозевают момент с управлением памятью.мусормус

Это - довольно дискуссионный вопрос, очевидно, что у авторов было ТЗ от Google, чьи задачи и решает язык. Собственно, об этом и авторы рассказывали: низкий порог входа, гарантированная надёжность кода, быстрая компиляция. Очевидно, что какой-то фактор помешал найти подходящую реализацию без GC, возможно, время.

Как работают исключения, Maybe возврат ошибок в C мне известно. Под явной обработкой и имел ввиду обработку непосредственно за вызовом. Именно решением этой проблемы сейчас и заняты разработчики языка, так как хотелось бы поместить один общий handler в пределах функции, и там обрабатывать все ошибки, которые не нужно обрабатывать на месте, собственно, примерно то, о чем вы и пишите. Если найду ссылку на rfc - могу сбросить, с ходу не нашел, но там предлагается что-то вроде defer, только для ошибок, опять же, если все правильно помню.

P.S.: Если с телефона, то там внизу для нового абзаца есть tool buttons, а если с ПК, то /.

Обработка ошибок, действительно, неудобна, над этим вроде как работают, но перспективы, судя по предложениям, все ещё туманны. А в чем беда? В том, что каждый вызов нужно явно обрабатывать? Если так, то соглашусь с вами, если же нет, то объясните, пожалуйста, что имеете ввиду.

Отсутствие дженериков - это, безусловно, боль, но это не означает, что вот вашу конкретную задачу невозможно решить. Нужно начать мыслить иначе, так как в Go такие штуки реализуется, так сказать, наизнанку. Вот вам пример Реализации универсальной функции `Includes()` грубо и на коленке за несколько минут, пожалуй, можно и поизящней придумать:

Решение с итератором
package main

import "fmt"

type Iterator interface {
	HasNext() bool
	Next()
	Get() interface{}
}

type Iterable interface {
	MakeIterator() Iterator
}

type Comparable interface {
	Iterable
	Eq(it Iterator, v interface{}) bool
}

func Includes(sl Comparable, v interface{}) bool {
	for it := sl.MakeIterator(); it.HasNext(); it.Next() {
		if sl.Eq(it, v) {
			return true
		}
	}

	return false
}

type IntSlice []int

func (isl *IntSlice) Eq(it Iterator, v interface{}) bool {
	return it.Get() == v
}

func (isl *IntSlice) MakeIterator() Iterator {
	return NewIntSliceInterator(isl)
}

type IntSliceIterator struct {
	isl   *IntSlice
	index int
}

func NewIntSliceInterator(isl *IntSlice) *IntSliceIterator {
	return &IntSliceIterator{isl: isl}
}

func (it *IntSliceIterator) HasNext() bool {
	return it.index < len(*it.isl)-1
}

func (it *IntSliceIterator) Next() {
	if it.index < len(*it.isl)-1 {
		it.index++
	}
}

func (it *IntSliceIterator) Get() interface{} {
	return (*it.isl)[it.index]
}

func main() {
	arr := IntSlice{1, 2, 3, 4, 5}

	fmt.Printf("arr: %v includes %d: %t\n", arr, 4, Includes(&arr, 4))
	fmt.Printf("arr: %v includes %d: %t\n", arr, 0, Includes(&arr, 0))
}
Чуть более примитивный вариант для типовых срезов
package main

import "fmt"

type Comparable interface {
	Len() int
	Eq(index int, v interface{}) bool
}

func Includes(sl Comparable, v interface{}) bool {
	for i := 0; i < sl.Len(); i++ {
		if sl.Eq(i, v) {
			return true
		}
	}

	return false
}

type IntSlice []int

func (isl *IntSlice) Len() int {
	return len(*isl)
}

func (isl *IntSlice) Eq(index int, v interface{}) bool {
	return (*isl)[index] == v
}

func main() {
	arr := IntSlice{1, 2, 3, 4, 5}

	fmt.Printf("arr: %v includes %d: %t\n", arr, 4, Includes(&arr, 4))
	fmt.Printf("arr: %v includes %d: %t\n", arr, 0, Includes(&arr, 0))
}

Да, дженерики позволят решать такие задачи почти также красиво, как в других языках, а тут пока вам нужно реализовать либо примерно также, как это сделано в `sort.Sort`, либо через итераторы. И пока возникает резонный вопрос: а стоит ли овчинка выделки, ведь банальный поиск можно сделать через ту же лямбду, и, кажется, он будет короче по количеству строк:

package main

import "fmt"

func main() {
	arr := []int{1, 2, 3, 4, 5}

	includes := func(arr []int, value int) bool {
		for _, v := range arr {
			if v == value {
				return true
			}
		}

		return false
	}

	fmt.Printf("arr: %v includes %d: %t\n", arr, 4, includes(arr, 4))
	fmt.Printf("arr: %v includes %d: %t\n", arr, 0, includes(arr, 0))
}

Сторонники Go скажут, что вам тут сам язык предлагает задуматься: "если я часто делаю операции поиска с несколькими типами срезов, то почему бы мне не унифицировать процесс, реализовав универсальную функцию Includes, а если у меня каждый раз разные типы, то, может, проще сделать поиск на месте?" Но вот я, как человек, который уже более двух лет пишет на Go, могу сказать, что тут это просто неудобно, потому что много однообразного кода приходится писать.

Ну какой же это функциональный язык? Если вы хотели сказать процедурный, то это тоже не совсем верно, потому что ООП там есть, более-менее полноценный, без классов, да, но классы - не основа ООП, можно похоливарить на тему инкапсуляции, но в python ее тогда тоже нет.

Что касается наследования, то его нет, но есть композиция, вкладываете одну структуру в другую и она может вызывать ее методы:

package main

import "fmt"

type Printer struct {
  value string
}

func NewPrinter(value string) *Printer {
  return &Printer{value: value}
}

func (p Printer) Print() string {
  return p.value
}

type ComboPrinter struct {
  Print
  id int
}

func NewComboPrinter(id int, value string) *ComboPrinter {
  return &ComboPrinter {
    Printer: *NewPrinter(value),
    id: id,
  }
}

func (cp ComboPrinter) PrintCombo() string {
  return fmt.Sprintf("%d: %s", cp.id, cp.Print())
}

func main() {
  cp := ComboPrinter{}
  
  fmt.Println(cp.PrintCombo())
  fmt.Println(cp.Print())
}

Таким же образом можно и интерфейсы внедрять в структуры (правда, пока не придумал - зачем в реальном проекте такое).

Про пакет sort вам уже выше сказали, да, не очень удобно, но есть. Тут другая парадигма, и стоит отбросить свои привычки из php и изучить язык поглубже.

Что касается поиска ключа в map - такая функция есть:

value, ok := mymap["search_key"]

if ok {
  // do something
} else {
  // no key
}

Да, пожалуй, неверно выразился. Конечно, речь о том, чтоб все это выполнялось за один проход цикла. Собственно, если не ошибаюсь (не силен в ФП), некоторые языки такое позволяют на этапе компиляции. Не отношусь к фанатам подобных конструкций как раз из-за множества проходов, отсутствия break, не говоря уже о том, что сам по себе forEach и любой из его собратьев медленнее обычного for, хотя сейчас уже прикрутили какие-то оптимизации в движках.

Прошу прощения, случайно на телефоне на минус пальцем нажал, так что в качестве компенсации от меня плюс в карму.

Вообще, да, хотелось бы иметь интерпретатор для JS, ну или хотя бы компилятор типа TS, который умеет вызовы типа arr.map(...).filter(...).reduce(...) разворачивать в O(n).

Например, отсюда.

Старые модули остались под LGPL, может, и какие-то новые тоже под LGPL, но есть и масса тех, что под GPL, что я и сказал в предыдущем комментарии. Если хотите знать точные имена - можете самостоятельно поизучать документацию или исходники. В основном, это касалось QtQuick-компонентов, но то было несколько лет назад, как сейчас ситуация обстоит - надо уточнять. Но факт есть факт: без коммерческой лицензии нельзя полностью использовать Qt в закрытых проектах.

Позвольте поинтересоваться: с какой именно частью текста статьи вы не согласны? Если все претензии только к заголовку, то, каюсь, он немного желтоват, но лишь с благой целью привлечения внимания к содержанию.

Стоимость коммерческой лицензии, без которой на современном Qt почти нереально написать приложение, так как все новые компоненты под GPLv3, если мне не изменяет память. То есть там двойное лицензирование коммерческая + разные варианты (L)GPL для разных моделей. Раньше была возможность использовать LGPLv2 и просто размещать библиотеки Qt рядом со своим бинарником, а теперь либо open source, либо плати. Где-то пол года назад смотрел, на одно разработчика а год было около 75-80к р., причем лицензию по их условиям нужно оплатить до начала разработки. В общем для каких-то личных проектов с туманной перспективой монетизации предложение не выглядит привлекательно, как и для небольших команд в стартапах. Да и lts-патчи теперь только по платной подписке. В общем, они решили сосредоточиться на крупных клиентах и забить на сообщество (мое личное мнение).

У Qt все прекрасно, кроме условий лицензирования.

Вам уже выше иносказательно посредством анекдота объяснили, что форк без поддержки не имеет смысла, а в комментарии выше я попытался объяснить - почему. Если для вас вывод неочевиден, то ничем не могу вам помочь.

Большинство этих форков существует только за счет того, что постоянно мерджат себе изменения из апстрима. Не будет развития апстрима - не будет и их развития со всеми вытекающими.

Подобный пример приведен на странице документации. Я уже давно использую Composition API, поэтому мой пример будет выглядеть примерно вот так:

<template>
  <div :class="componentClass"></div>
</template>

<script lang="ts">
// Vue 2 + Vue Composition API plugin + TypeScript
import { defineComponent, computed } from '@vue/composition-api';
 
interface Props {
  disabled?: boolean;
  highlight?: boolean;
  strong?: boolean;
}
  
function setup(props: Props) {
  const componentClass = computed(() => {
    let color: string;
    
    if (props.highlight) color = 'highlight';
    else if (props.strong) color = 'strong';
    else color = 'normal';

    return {
    	disabled: Boolean(props.disabled),
      [color]: true
    };
  });
  
  return { componentClass };
}

export default defineComponent({
  props: {
    disabled: Boolean,
    highlight: Boolean,
    strong: Boolean
  },
  
  setup
});
</script>

<style scoped>
.normal {
  color: #535353;
}
  
.highlight {
  color: #30de30;
}

.strong {
  color: #303030;
}
  
.disabled {
  color: #939393;
  user-select: none;
}
</style>

В свойство класс можно передать объект с полями - именами классов и булевыми значениями (добавить/не добавлять) (в том числе computed). Генерируйте объект и передавайте лишь его в класс вместо вот этой вот портянки в шаблоне. (Частное, не претендующее на звание истины мнение).

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность